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 64 of file findtimezone.c.

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

Referenced by tzloadbody().

65 {
66  char fullname[MAXPGPATH];
67 
68  if (canonname)
69  strlcpy(canonname, name, TZ_STRLEN_MAX + 1);
70 
71  strlcpy(fullname, pg_TZDIR(), sizeof(fullname));
72  if (strlen(fullname) + 1 + strlen(name) >= MAXPGPATH)
73  return -1; /* not gonna fit */
74  strcat(fullname, "/");
75  strcat(fullname, name);
76 
77  return open(fullname, O_RDONLY | PG_BINARY, 0);
78 }
static const char * pg_TZDIR(void)
Definition: findtimezone.c:36
#define PG_BINARY
Definition: c.h:1080
#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 555 of file localtime.c.

References free, malloc, and tzloadbody().

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

556 {
557  union local_storage *lsp = malloc(sizeof *lsp);
558 
559  if (!lsp)
560  return errno;
561  else
562  {
563  int err = tzloadbody(name, canonname, sp, doextend, lsp);
564 
565  free(lsp);
566  return err;
567  }
568 }
static int tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend, union local_storage *lsp)
Definition: localtime.c:213
#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 896 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, name, SECSPERDAY, SECSPERHOUR, swap, state::timecnt, timecnt, transtime(), ttinfo::tt_gmtoff, ttinfo::tt_isdst, ttinfo::tt_ttisgmt, ttinfo::tt_ttisstd, state::ttis, state::typecnt, state::types, TZ_MAX_TIMES, TZDEFRULES, tzdefrules_loaded, tzdefrules_s, TZDEFRULESTRING, tzload(), year_lengths, and YEARSPERREPEAT.

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

897 {
898  const char *stdname;
899  const char *dstname = NULL;
900  size_t stdlen;
901  size_t dstlen;
902  size_t charcnt;
903  int32 stdoffset;
904  int32 dstoffset;
905  char *cp;
906  bool load_ok;
907 
908  stdname = name;
909  if (lastditch)
910  {
911  /*
912  * This is intentionally somewhat different from the IANA code. We do
913  * not want to invoke tzload() in the lastditch case: we can't assume
914  * pg_open_tzfile() is sane yet, and we don't care about leap seconds
915  * anyway.
916  */
917  stdlen = strlen(name); /* length of standard zone name */
918  name += stdlen;
919  if (stdlen >= sizeof sp->chars)
920  stdlen = (sizeof sp->chars) - 1;
921  charcnt = stdlen + 1;
922  stdoffset = 0;
923  sp->goback = sp->goahead = false; /* simulate failed tzload() */
924  load_ok = false;
925  }
926  else
927  {
928  if (*name == '<')
929  {
930  name++;
931  stdname = name;
932  name = getqzname(name, '>');
933  if (*name != '>')
934  return false;
935  stdlen = name - stdname;
936  name++;
937  }
938  else
939  {
940  name = getzname(name);
941  stdlen = name - stdname;
942  }
943  if (*name == '\0') /* we allow empty STD abbrev, unlike IANA */
944  return false;
945  name = getoffset(name, &stdoffset);
946  if (name == NULL)
947  return false;
948  charcnt = stdlen + 1;
949  if (sizeof sp->chars < charcnt)
950  return false;
951 
952  /*
953  * This bit also differs from the IANA code, which doesn't make any
954  * attempt to avoid repetitive loadings of the TZDEFRULES zone.
955  */
956  if (tzdefrules_loaded == 0)
957  {
958  if (tzload(TZDEFRULES, NULL, &tzdefrules_s, false) == 0)
959  tzdefrules_loaded = 1;
960  else
961  tzdefrules_loaded = -1;
962  }
963  load_ok = (tzdefrules_loaded > 0);
964  if (load_ok)
965  memcpy(sp, &tzdefrules_s, sizeof(struct state));
966  }
967  if (!load_ok)
968  sp->leapcnt = 0; /* so, we're off a little */
969  if (*name != '\0')
970  {
971  if (*name == '<')
972  {
973  dstname = ++name;
974  name = getqzname(name, '>');
975  if (*name != '>')
976  return false;
977  dstlen = name - dstname;
978  name++;
979  }
980  else
981  {
982  dstname = name;
983  name = getzname(name);
984  dstlen = name - dstname; /* length of DST zone name */
985  }
986  if (!dstlen)
987  return false;
988  charcnt += dstlen + 1;
989  if (sizeof sp->chars < charcnt)
990  return false;
991  if (*name != '\0' && *name != ',' && *name != ';')
992  {
993  name = getoffset(name, &dstoffset);
994  if (name == NULL)
995  return false;
996  }
997  else
998  dstoffset = stdoffset - SECSPERHOUR;
999  if (*name == '\0' && !load_ok)
1001  if (*name == ',' || *name == ';')
1002  {
1003  struct rule start;
1004  struct rule end;
1005  int year;
1006  int yearlim;
1007  int timecnt;
1008  pg_time_t janfirst;
1009  int32 janoffset = 0;
1010  int yearbeg;
1011 
1012  ++name;
1013  if ((name = getrule(name, &start)) == NULL)
1014  return false;
1015  if (*name++ != ',')
1016  return false;
1017  if ((name = getrule(name, &end)) == NULL)
1018  return false;
1019  if (*name != '\0')
1020  return false;
1021  sp->typecnt = 2; /* standard time and DST */
1022 
1023  /*
1024  * Two transitions per year, from EPOCH_YEAR forward.
1025  */
1026  init_ttinfo(&sp->ttis[0], -dstoffset, true, stdlen + 1);
1027  init_ttinfo(&sp->ttis[1], -stdoffset, false, 0);
1028  sp->defaulttype = 0;
1029  timecnt = 0;
1030  janfirst = 0;
1031  yearbeg = EPOCH_YEAR;
1032 
1033  do
1034  {
1035  int32 yearsecs
1036  = year_lengths[isleap(yearbeg - 1)] * SECSPERDAY;
1037 
1038  yearbeg--;
1039  if (increment_overflow_time(&janfirst, -yearsecs))
1040  {
1041  janoffset = -yearsecs;
1042  break;
1043  }
1044  } while (EPOCH_YEAR - YEARSPERREPEAT / 2 < yearbeg);
1045 
1046  yearlim = yearbeg + YEARSPERREPEAT + 1;
1047  for (year = yearbeg; year < yearlim; year++)
1048  {
1049  int32
1050  starttime = transtime(year, &start, stdoffset),
1051  endtime = transtime(year, &end, dstoffset);
1052  int32
1053  yearsecs = (year_lengths[isleap(year)]
1054  * SECSPERDAY);
1055  bool reversed = endtime < starttime;
1056 
1057  if (reversed)
1058  {
1059  int32 swap = starttime;
1060 
1061  starttime = endtime;
1062  endtime = swap;
1063  }
1064  if (reversed
1065  || (starttime < endtime
1066  && (endtime - starttime
1067  < (yearsecs
1068  + (stdoffset - dstoffset)))))
1069  {
1070  if (TZ_MAX_TIMES - 2 < timecnt)
1071  break;
1072  sp->ats[timecnt] = janfirst;
1074  (&sp->ats[timecnt],
1075  janoffset + starttime))
1076  sp->types[timecnt++] = reversed;
1077  else if (janoffset)
1078  sp->defaulttype = reversed;
1079  sp->ats[timecnt] = janfirst;
1081  (&sp->ats[timecnt],
1082  janoffset + endtime))
1083  {
1084  sp->types[timecnt++] = !reversed;
1085  yearlim = year + YEARSPERREPEAT + 1;
1086  }
1087  else if (janoffset)
1088  sp->defaulttype = !reversed;
1089  }
1091  (&janfirst, janoffset + yearsecs))
1092  break;
1093  janoffset = 0;
1094  }
1095  sp->timecnt = timecnt;
1096  if (!timecnt)
1097  sp->typecnt = 1; /* Perpetual DST. */
1098  else if (YEARSPERREPEAT < year - yearbeg)
1099  sp->goback = sp->goahead = true;
1100  }
1101  else
1102  {
1103  int32 theirstdoffset;
1104  int32 theirdstoffset;
1105  int32 theiroffset;
1106  bool isdst;
1107  int i;
1108  int j;
1109 
1110  if (*name != '\0')
1111  return false;
1112 
1113  /*
1114  * Initial values of theirstdoffset and theirdstoffset.
1115  */
1116  theirstdoffset = 0;
1117  for (i = 0; i < sp->timecnt; ++i)
1118  {
1119  j = sp->types[i];
1120  if (!sp->ttis[j].tt_isdst)
1121  {
1122  theirstdoffset =
1123  -sp->ttis[j].tt_gmtoff;
1124  break;
1125  }
1126  }
1127  theirdstoffset = 0;
1128  for (i = 0; i < sp->timecnt; ++i)
1129  {
1130  j = sp->types[i];
1131  if (sp->ttis[j].tt_isdst)
1132  {
1133  theirdstoffset =
1134  -sp->ttis[j].tt_gmtoff;
1135  break;
1136  }
1137  }
1138 
1139  /*
1140  * Initially we're assumed to be in standard time.
1141  */
1142  isdst = false;
1143  theiroffset = theirstdoffset;
1144 
1145  /*
1146  * Now juggle transition times and types tracking offsets as you
1147  * do.
1148  */
1149  for (i = 0; i < sp->timecnt; ++i)
1150  {
1151  j = sp->types[i];
1152  sp->types[i] = sp->ttis[j].tt_isdst;
1153  if (sp->ttis[j].tt_ttisgmt)
1154  {
1155  /* No adjustment to transition time */
1156  }
1157  else
1158  {
1159  /*
1160  * If daylight saving time is in effect, and the
1161  * transition time was not specified as standard time, add
1162  * the daylight saving time offset to the transition time;
1163  * otherwise, add the standard time offset to the
1164  * transition time.
1165  */
1166 
1167  /*
1168  * Transitions from DST to DDST will effectively disappear
1169  * since POSIX provides for only one DST offset.
1170  */
1171  if (isdst && !sp->ttis[j].tt_ttisstd)
1172  {
1173  sp->ats[i] += dstoffset -
1174  theirdstoffset;
1175  }
1176  else
1177  {
1178  sp->ats[i] += stdoffset -
1179  theirstdoffset;
1180  }
1181  }
1182  theiroffset = -sp->ttis[j].tt_gmtoff;
1183  if (sp->ttis[j].tt_isdst)
1184  theirdstoffset = theiroffset;
1185  else
1186  theirstdoffset = theiroffset;
1187  }
1188 
1189  /*
1190  * Finally, fill in ttis.
1191  */
1192  init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1193  init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
1194  sp->typecnt = 2;
1195  sp->defaulttype = 0;
1196  }
1197  }
1198  else
1199  {
1200  dstlen = 0;
1201  sp->typecnt = 1; /* only standard time */
1202  sp->timecnt = 0;
1203  init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1204  sp->defaulttype = 0;
1205  }
1206  sp->charcnt = charcnt;
1207  cp = sp->chars;
1208  memcpy(cp, stdname, stdlen);
1209  cp += stdlen;
1210  *cp++ = '\0';
1211  if (dstlen != 0)
1212  {
1213  memcpy(cp, dstname, dstlen);
1214  *(cp + dstlen) = '\0';
1215  }
1216  return true;
1217 }
#define swap(a, b)
Definition: qsort.c:94
static const char * getoffset(const char *strp, int32 *offsetp)
Definition: localtime.c:713
static void init_ttinfo(struct ttinfo *s, int32 gmtoff, bool isdst, int abbrind)
Definition: localtime.c:110
int64 pg_time_t
Definition: pgtime.h:23
int tzload(const char *name, char *canonname, struct state *sp, bool doextend)
Definition: localtime.c:555
int charcnt
Definition: pgtz.h:46
bool goback
Definition: pgtz.h:47
int32 tt_gmtoff
Definition: pgtz.h:28
#define SECSPERDAY
Definition: private.h:97
#define isleap(y)
Definition: datetime.h:273
int leapcnt
Definition: pgtz.h:43
static const char * getrule(const char *strp, struct rule *rulep)
Definition: localtime.c:739
#define SECSPERHOUR
Definition: private.h:96
#define TZ_MAX_TIMES
Definition: tzfile.h:93
pg_time_t ats[TZ_MAX_TIMES]
Definition: pgtz.h:49
#define TZDEFRULESTRING
Definition: localtime.c:66
Definition: localtime.c:77
signed int int32
Definition: c.h:313
bool tt_isdst
Definition: pgtz.h:29
static struct state tzdefrules_s
Definition: localtime.c:57
char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS+1, 3),(2 *(TZ_STRLEN_MAX+1)))]
Definition: pgtz.h:53
static int32 transtime(int year, const struct rule *rulep, int32 offset)
Definition: localtime.c:799
#define EPOCH_YEAR
Definition: private.h:123
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:58
Definition: regguts.h:298
#define TZDEFRULES
Definition: tzfile.h:25
static ptrdiff_t timecnt
Definition: zic.c:192
int timecnt
Definition: pgtz.h:44
static int charcnt
Definition: zic.c:173
bool tt_ttisstd
Definition: pgtz.h:31
const char * name
Definition: encode.c:521
#define YEARSPERREPEAT
Definition: private.h:88
static bool increment_overflow_time(pg_time_t *, int32)
Definition: localtime.c:1522
static const int year_lengths[2]
Definition: localtime.c:599
int i
bool tt_ttisgmt
Definition: pgtz.h:32
bool goahead
Definition: pgtz.h:48
static const char * getqzname(const char *strp, int delim)
Definition: localtime.c:628
int typecnt
Definition: pgtz.h:45
int defaulttype
Definition: pgtz.h:55
static const char * getzname(const char *strp)
Definition: localtime.c:609