PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
findtimezone.c File Reference
#include "postgres_fe.h"
#include <fcntl.h>
#include <sys/stat.h>
#include <time.h>
#include "pgtz.h"
Include dependency graph for findtimezone.c:

Go to the source code of this file.

Data Structures

struct  tztry
 

Macros

#define T_DAY   ((time_t) (60*60*24))
 
#define T_WEEK   ((time_t) (60*60*24*7))
 
#define T_MONTH   ((time_t) (60*60*24*31))
 
#define MAX_TEST_TIMES   (52*100) /* 100 years */
 

Functions

const char * select_default_timezone (const char *share_path)
 
static const char * pg_TZDIR (void)
 
int pg_open_tzfile (const char *name, char *canonname)
 
static pg_tzpg_load_tz (const char *name)
 
static void scan_available_timezones (char *tzdir, char *tzdirsub, struct tztry *tt, int *bestscore, char *bestzonename)
 
static int get_timezone_offset (struct tm *tm)
 
static time_t build_time_t (int year, int month, int day)
 
static bool compare_tm (struct tm *s, struct pg_tm *p)
 
static int score_timezone (const char *tzname, struct tztry *tt)
 
static const char * identify_system_timezone (void)
 
static bool validate_zone (const char *tzname)
 

Variables

static char tzdirpath [MAXPGPATH]
 

Macro Definition Documentation

#define MAX_TEST_TIMES   (52*100) /* 100 years */

Definition at line 145 of file findtimezone.c.

Referenced by identify_system_timezone().

#define T_DAY   ((time_t) (60*60*24))

Definition at line 141 of file findtimezone.c.

Referenced by identify_system_timezone().

#define T_MONTH   ((time_t) (60*60*24*31))

Definition at line 143 of file findtimezone.c.

Referenced by identify_system_timezone().

#define T_WEEK   ((time_t) (60*60*24*7))

Definition at line 142 of file findtimezone.c.

Referenced by identify_system_timezone().

Function Documentation

static time_t build_time_t ( int  year,
int  month,
int  day 
)
static

Definition at line 177 of file findtimezone.c.

References tm.

Referenced by identify_system_timezone().

178 {
179  struct tm tm;
180 
181  memset(&tm, 0, sizeof(tm));
182  tm.tm_mday = day;
183  tm.tm_mon = month - 1;
184  tm.tm_year = year - 1900;
185 
186  return mktime(&tm);
187 }
static struct pg_tm tm
Definition: localtime.c:107
int tm_mday
Definition: pgtime.h:30
int tm_mon
Definition: pgtime.h:31
int tm_year
Definition: pgtime.h:32
static bool compare_tm ( struct tm s,
struct pg_tm p 
)
static

Definition at line 193 of file findtimezone.c.

References pg_tm::tm_hour, pg_tm::tm_isdst, pg_tm::tm_mday, pg_tm::tm_min, pg_tm::tm_mon, pg_tm::tm_sec, pg_tm::tm_wday, pg_tm::tm_yday, and pg_tm::tm_year.

Referenced by score_timezone().

194 {
195  if (s->tm_sec != p->tm_sec ||
196  s->tm_min != p->tm_min ||
197  s->tm_hour != p->tm_hour ||
198  s->tm_mday != p->tm_mday ||
199  s->tm_mon != p->tm_mon ||
200  s->tm_year != p->tm_year ||
201  s->tm_wday != p->tm_wday ||
202  s->tm_yday != p->tm_yday ||
203  s->tm_isdst != p->tm_isdst)
204  return false;
205  return true;
206 }
int tm_wday
Definition: pgtime.h:33
int tm_isdst
Definition: pgtime.h:35
int tm_hour
Definition: pgtime.h:29
int tm_mday
Definition: pgtime.h:30
int tm_mon
Definition: pgtime.h:31
int tm_year
Definition: pgtime.h:32
int tm_yday
Definition: pgtime.h:34
int tm_sec
Definition: pgtime.h:27
int tm_min
Definition: pgtime.h:28
static int get_timezone_offset ( struct tm tm)
static

Definition at line 162 of file findtimezone.c.

References TIMEZONE_GLOBAL.

Referenced by identify_system_timezone().

163 {
164 #if defined(HAVE_STRUCT_TM_TM_ZONE)
165  return tm->tm_gmtoff;
166 #elif defined(HAVE_INT_TIMEZONE)
167  return -TIMEZONE_GLOBAL;
168 #else
169 #error No way to determine TZ? Can this happen?
170 #endif
171 }
#define TIMEZONE_GLOBAL
Definition: port.h:225
long int tm_gmtoff
Definition: pgtime.h:36
static struct pg_tm tm
Definition: localtime.c:107
static const char* identify_system_timezone ( void  )
static

Definition at line 310 of file findtimezone.c.

References build_time_t(), get_timezone_offset(), MAX_TEST_TIMES, MAXPGPATH, tztry::n_test_times, pg_TZDIR(), scan_available_timezones(), score_timezone(), snprintf(), strlcpy(), T_DAY, T_MONTH, T_WEEK, tztry::test_times, tm, and TZ_STRLEN_MAX.

Referenced by select_default_timezone().

311 {
312  static char resultbuf[TZ_STRLEN_MAX + 1];
313  time_t tnow;
314  time_t t;
315  struct tztry tt;
316  struct tm *tm;
317  int thisyear;
318  int bestscore;
319  char tmptzdir[MAXPGPATH];
320  int std_ofs;
321  char std_zone_name[TZ_STRLEN_MAX + 1],
322  dst_zone_name[TZ_STRLEN_MAX + 1];
323  char cbuf[TZ_STRLEN_MAX + 1];
324 
325  /* Initialize OS timezone library */
326  tzset();
327 
328  /*
329  * Set up the list of dates to be probed to see how well our timezone
330  * matches the system zone. We first probe January and July of the
331  * current year; this serves to quickly eliminate the vast majority of the
332  * TZ database entries. If those dates match, we probe every week for 100
333  * years backwards from the current July. (Weekly resolution is good
334  * enough to identify DST transition rules, since everybody switches on
335  * Sundays.) This is sufficient to cover most of the Unix time_t range,
336  * and we don't want to look further than that since many systems won't
337  * have sane TZ behavior further back anyway. The further back the zone
338  * matches, the better we score it. This may seem like a rather random
339  * way of doing things, but experience has shown that system-supplied
340  * timezone definitions are likely to have DST behavior that is right for
341  * the recent past and not so accurate further back. Scoring in this way
342  * allows us to recognize zones that have some commonality with the Olson
343  * database, without insisting on exact match. (Note: we probe Thursdays,
344  * not Sundays, to avoid triggering DST-transition bugs in localtime
345  * itself.)
346  */
347  tnow = time(NULL);
348  tm = localtime(&tnow);
349  if (!tm)
350  return NULL; /* give up if localtime is broken... */
351  thisyear = tm->tm_year + 1900;
352 
353  t = build_time_t(thisyear, 1, 15);
354 
355  /*
356  * Round back to GMT midnight Thursday. This depends on the knowledge
357  * that the time_t origin is Thu Jan 01 1970. (With a different origin
358  * we'd be probing some other day of the week, but it wouldn't matter
359  * anyway unless localtime() had DST-transition bugs.)
360  */
361  t -= (t % T_WEEK);
362 
363  tt.n_test_times = 0;
364  tt.test_times[tt.n_test_times++] = t;
365 
366  t = build_time_t(thisyear, 7, 15);
367  t -= (t % T_WEEK);
368 
369  tt.test_times[tt.n_test_times++] = t;
370 
371  while (tt.n_test_times < MAX_TEST_TIMES)
372  {
373  t -= T_WEEK;
374  tt.test_times[tt.n_test_times++] = t;
375  }
376 
377  /* Search for the best-matching timezone file */
378  strlcpy(tmptzdir, pg_TZDIR(), sizeof(tmptzdir));
379  bestscore = -1;
380  resultbuf[0] = '\0';
381  scan_available_timezones(tmptzdir, tmptzdir + strlen(tmptzdir) + 1,
382  &tt,
383  &bestscore, resultbuf);
384  if (bestscore > 0)
385  {
386  /* Ignore Olson's rather silly "Factory" zone; use GMT instead */
387  if (strcmp(resultbuf, "Factory") == 0)
388  return NULL;
389  return resultbuf;
390  }
391 
392  /*
393  * Couldn't find a match in the database, so next we try constructed zone
394  * names (like "PST8PDT").
395  *
396  * First we need to determine the names of the local standard and daylight
397  * zones. The idea here is to scan forward from today until we have seen
398  * both zones, if both are in use.
399  */
400  memset(std_zone_name, 0, sizeof(std_zone_name));
401  memset(dst_zone_name, 0, sizeof(dst_zone_name));
402  std_ofs = 0;
403 
404  tnow = time(NULL);
405 
406  /*
407  * Round back to a GMT midnight so results don't depend on local time of
408  * day
409  */
410  tnow -= (tnow % T_DAY);
411 
412  /*
413  * We have to look a little further ahead than one year, in case today is
414  * just past a DST boundary that falls earlier in the year than the next
415  * similar boundary. Arbitrarily scan up to 14 months.
416  */
417  for (t = tnow; t <= tnow + T_MONTH * 14; t += T_MONTH)
418  {
419  tm = localtime(&t);
420  if (!tm)
421  continue;
422  if (tm->tm_isdst < 0)
423  continue;
424  if (tm->tm_isdst == 0 && std_zone_name[0] == '\0')
425  {
426  /* found STD zone */
427  memset(cbuf, 0, sizeof(cbuf));
428  strftime(cbuf, sizeof(cbuf) - 1, "%Z", tm); /* zone abbr */
429  strcpy(std_zone_name, cbuf);
430  std_ofs = get_timezone_offset(tm);
431  }
432  if (tm->tm_isdst > 0 && dst_zone_name[0] == '\0')
433  {
434  /* found DST zone */
435  memset(cbuf, 0, sizeof(cbuf));
436  strftime(cbuf, sizeof(cbuf) - 1, "%Z", tm); /* zone abbr */
437  strcpy(dst_zone_name, cbuf);
438  }
439  /* Done if found both */
440  if (std_zone_name[0] && dst_zone_name[0])
441  break;
442  }
443 
444  /* We should have found a STD zone name by now... */
445  if (std_zone_name[0] == '\0')
446  {
447 #ifdef DEBUG_IDENTIFY_TIMEZONE
448  fprintf(stderr, "could not determine system time zone\n");
449 #endif
450  return NULL; /* go to GMT */
451  }
452 
453  /* If we found DST then try STD<ofs>DST */
454  if (dst_zone_name[0] != '\0')
455  {
456  snprintf(resultbuf, sizeof(resultbuf), "%s%d%s",
457  std_zone_name, -std_ofs / 3600, dst_zone_name);
458  if (score_timezone(resultbuf, &tt) > 0)
459  return resultbuf;
460  }
461 
462  /* Try just the STD timezone (works for GMT at least) */
463  strcpy(resultbuf, std_zone_name);
464  if (score_timezone(resultbuf, &tt) > 0)
465  return resultbuf;
466 
467  /* Try STD<ofs> */
468  snprintf(resultbuf, sizeof(resultbuf), "%s%d",
469  std_zone_name, -std_ofs / 3600);
470  if (score_timezone(resultbuf, &tt) > 0)
471  return resultbuf;
472 
473  /*
474  * Did not find the timezone. Fallback to use a GMT zone. Note that the
475  * Olson timezone database names the GMT-offset zones in POSIX style: plus
476  * is west of Greenwich. It's unfortunate that this is opposite of SQL
477  * conventions. Should we therefore change the names? Probably not...
478  */
479  snprintf(resultbuf, sizeof(resultbuf), "Etc/GMT%s%d",
480  (-std_ofs > 0) ? "+" : "", -std_ofs / 3600);
481 
482 #ifdef DEBUG_IDENTIFY_TIMEZONE
483  fprintf(stderr, "could not recognize system time zone, using \"%s\"\n",
484  resultbuf);
485 #endif
486  return resultbuf;
487 }
#define T_DAY
Definition: findtimezone.c:141
static void scan_available_timezones(char *tzdir, char *tzdirsub, struct tztry *tt, int *bestscore, char *bestzonename)
Definition: findtimezone.c:509
#define T_MONTH
Definition: findtimezone.c:143
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
static const char * pg_TZDIR(void)
Definition: findtimezone.c:36
static struct pg_tm tm
Definition: localtime.c:107
#define TZ_STRLEN_MAX
Definition: pgtime.h:44
#define MAXPGPATH
static int get_timezone_offset(struct tm *tm)
Definition: findtimezone.c:162
static time_t build_time_t(int year, int month, int day)
Definition: findtimezone.c:177
#define T_WEEK
Definition: findtimezone.c:142
static int score_timezone(const char *tzname, struct tztry *tt)
Definition: findtimezone.c:220
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define MAX_TEST_TIMES
Definition: findtimezone.c:145
static pg_tz* pg_load_tz ( const char *  name)
static

Definition at line 90 of file findtimezone.c.

References pg_tz::state, TZ_STRLEN_MAX, tzload(), pg_tz::TZname, and tzparse().

Referenced by score_timezone(), and validate_zone().

91 {
92  static pg_tz tz;
93 
94  if (strlen(name) > TZ_STRLEN_MAX)
95  return NULL; /* not going to fit */
96 
97  /*
98  * "GMT" is always sent to tzparse(); see comments for pg_tzset().
99  */
100  if (strcmp(name, "GMT") == 0)
101  {
102  if (!tzparse(name, &tz.state, true))
103  {
104  /* This really, really should not happen ... */
105  return NULL;
106  }
107  }
108  else if (tzload(name, NULL, &tz.state, true) != 0)
109  {
110  if (name[0] == ':' || !tzparse(name, &tz.state, false))
111  {
112  return NULL; /* unknown timezone */
113  }
114  }
115 
116  strcpy(tz.TZname, name);
117 
118  return &tz;
119 }
int tzload(const char *name, char *canonname, struct state *sp, bool doextend)
Definition: localtime.c:556
#define TZ_STRLEN_MAX
Definition: pgtime.h:44
bool tzparse(const char *name, struct state *sp, bool lastditch)
Definition: localtime.c:897
struct state state
Definition: pgtz.h:63
Definition: pgtz.h:59
char TZname[TZ_STRLEN_MAX+1]
Definition: pgtz.h:62
const char * name
Definition: encode.c:521
int pg_open_tzfile ( const char *  name,
char *  canonname 
)

Definition at line 64 of file findtimezone.c.

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:1044
#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
static const char* pg_TZDIR ( void  )
static

Definition at line 36 of file findtimezone.c.

References tzdirpath.

Referenced by identify_system_timezone(), and pg_open_tzfile().

37 {
38 #ifndef SYSTEMTZDIR
39  /* normal case: timezone stuff is under our share dir */
40  return tzdirpath;
41 #else
42  /* we're configured to use system's timezone database */
43  return SYSTEMTZDIR;
44 #endif
45 }
static char tzdirpath[MAXPGPATH]
Definition: findtimezone.c:26
static void scan_available_timezones ( char *  tzdir,
char *  tzdirsub,
struct tztry tt,
int *  bestscore,
char *  bestzonename 
)
static

Definition at line 509 of file findtimezone.c.

References MAXPGPATH, name, pgfnames(), pgfnames_cleanup(), score_timezone(), snprintf(), strerror(), strlcpy(), and TZ_STRLEN_MAX.

Referenced by identify_system_timezone().

511 {
512  int tzdir_orig_len = strlen(tzdir);
513  char **names;
514  char **namep;
515 
516  names = pgfnames(tzdir);
517  if (!names)
518  return;
519 
520  for (namep = names; *namep; namep++)
521  {
522  char *name = *namep;
523  struct stat statbuf;
524 
525  /* Ignore . and .., plus any other "hidden" files */
526  if (name[0] == '.')
527  continue;
528 
529  snprintf(tzdir + tzdir_orig_len, MAXPGPATH - tzdir_orig_len,
530  "/%s", name);
531 
532  if (stat(tzdir, &statbuf) != 0)
533  {
534 #ifdef DEBUG_IDENTIFY_TIMEZONE
535  fprintf(stderr, "could not stat \"%s\": %s\n",
536  tzdir, strerror(errno));
537 #endif
538  tzdir[tzdir_orig_len] = '\0';
539  continue;
540  }
541 
542  if (S_ISDIR(statbuf.st_mode))
543  {
544  /* Recurse into subdirectory */
545  scan_available_timezones(tzdir, tzdirsub, tt,
546  bestscore, bestzonename);
547  }
548  else
549  {
550  /* Load and test this file */
551  int score = score_timezone(tzdirsub, tt);
552 
553  if (score > *bestscore)
554  {
555  *bestscore = score;
556  strlcpy(bestzonename, tzdirsub, TZ_STRLEN_MAX + 1);
557  }
558  else if (score == *bestscore)
559  {
560  /* Consider how to break a tie */
561  if (strlen(tzdirsub) < strlen(bestzonename) ||
562  (strlen(tzdirsub) == strlen(bestzonename) &&
563  strcmp(tzdirsub, bestzonename) < 0))
564  strlcpy(bestzonename, tzdirsub, TZ_STRLEN_MAX + 1);
565  }
566  }
567 
568  /* Restore tzdir */
569  tzdir[tzdir_orig_len] = '\0';
570  }
571 
572  pgfnames_cleanup(names);
573 }
char ** pgfnames(const char *path)
Definition: pgfnames.c:31
static void scan_available_timezones(char *tzdir, char *tzdirsub, struct tztry *tt, int *bestscore, char *bestzonename)
Definition: findtimezone.c:509
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define TZ_STRLEN_MAX
Definition: pgtime.h:44
#define MAXPGPATH
static int score_timezone(const char *tzname, struct tztry *tt)
Definition: findtimezone.c:220
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
void pgfnames_cleanup(char **filenames)
Definition: pgfnames.c:99
const char * name
Definition: encode.c:521
const char * strerror(int errnum)
Definition: strerror.c:19
static int score_timezone ( const char *  tzname,
struct tztry tt 
)
static

Definition at line 220 of file findtimezone.c.

References compare_tm(), i, tztry::n_test_times, pg_load_tz(), pg_localtime(), pg_tz_acceptable(), tztry::test_times, tm, pg_tm::tm_hour, pg_tm::tm_isdst, pg_tm::tm_mday, pg_tm::tm_min, pg_tm::tm_mon, pg_tm::tm_sec, pg_tm::tm_year, pg_tm::tm_zone, and TZ_STRLEN_MAX.

Referenced by identify_system_timezone(), and scan_available_timezones().

221 {
222  int i;
223  pg_time_t pgtt;
224  struct tm *systm;
225  struct pg_tm *pgtm;
226  char cbuf[TZ_STRLEN_MAX + 1];
227  pg_tz *tz;
228 
229  /* Load timezone definition */
230  tz = pg_load_tz(tzname);
231  if (!tz)
232  return -1; /* unrecognized zone name */
233 
234  /* Reject if leap seconds involved */
235  if (!pg_tz_acceptable(tz))
236  {
237 #ifdef DEBUG_IDENTIFY_TIMEZONE
238  fprintf(stderr, "Reject TZ \"%s\": uses leap seconds\n", tzname);
239 #endif
240  return -1;
241  }
242 
243  /* Check for match at all the test times */
244  for (i = 0; i < tt->n_test_times; i++)
245  {
246  pgtt = (pg_time_t) (tt->test_times[i]);
247  pgtm = pg_localtime(&pgtt, tz);
248  if (!pgtm)
249  return -1; /* probably shouldn't happen */
250  systm = localtime(&(tt->test_times[i]));
251  if (!systm)
252  {
253 #ifdef DEBUG_IDENTIFY_TIMEZONE
254  fprintf(stderr, "TZ \"%s\" scores %d: at %ld %04d-%02d-%02d %02d:%02d:%02d %s, system had no data\n",
255  tzname, i, (long) pgtt,
256  pgtm->tm_year + 1900, pgtm->tm_mon + 1, pgtm->tm_mday,
257  pgtm->tm_hour, pgtm->tm_min, pgtm->tm_sec,
258  pgtm->tm_isdst ? "dst" : "std");
259 #endif
260  return i;
261  }
262  if (!compare_tm(systm, pgtm))
263  {
264 #ifdef DEBUG_IDENTIFY_TIMEZONE
265  fprintf(stderr, "TZ \"%s\" scores %d: at %ld %04d-%02d-%02d %02d:%02d:%02d %s versus %04d-%02d-%02d %02d:%02d:%02d %s\n",
266  tzname, i, (long) pgtt,
267  pgtm->tm_year + 1900, pgtm->tm_mon + 1, pgtm->tm_mday,
268  pgtm->tm_hour, pgtm->tm_min, pgtm->tm_sec,
269  pgtm->tm_isdst ? "dst" : "std",
270  systm->tm_year + 1900, systm->tm_mon + 1, systm->tm_mday,
271  systm->tm_hour, systm->tm_min, systm->tm_sec,
272  systm->tm_isdst ? "dst" : "std");
273 #endif
274  return i;
275  }
276  if (systm->tm_isdst >= 0)
277  {
278  /* Check match of zone names, too */
279  if (pgtm->tm_zone == NULL)
280  return -1; /* probably shouldn't happen */
281  memset(cbuf, 0, sizeof(cbuf));
282  strftime(cbuf, sizeof(cbuf) - 1, "%Z", systm); /* zone abbr */
283  if (strcmp(cbuf, pgtm->tm_zone) != 0)
284  {
285 #ifdef DEBUG_IDENTIFY_TIMEZONE
286  fprintf(stderr, "TZ \"%s\" scores %d: at %ld \"%s\" versus \"%s\"\n",
287  tzname, i, (long) pgtt,
288  pgtm->tm_zone, cbuf);
289 #endif
290  return i;
291  }
292  }
293  }
294 
295 #ifdef DEBUG_IDENTIFY_TIMEZONE
296  fprintf(stderr, "TZ \"%s\" gets max score %d\n", tzname, i);
297 #endif
298 
299  return i;
300 }
int64 pg_time_t
Definition: pgtime.h:23
int tm_isdst
Definition: pgtime.h:35
int tm_hour
Definition: pgtime.h:29
time_t test_times[MAX_TEST_TIMES]
Definition: findtimezone.c:150
Definition: pgtime.h:25
static pg_tz * pg_load_tz(const char *name)
Definition: findtimezone.c:90
static struct pg_tm tm
Definition: localtime.c:107
#define TZ_STRLEN_MAX
Definition: pgtime.h:44
static bool compare_tm(struct tm *s, struct pg_tm *p)
Definition: findtimezone.c:193
int tm_mday
Definition: pgtime.h:30
int tm_mon
Definition: pgtime.h:31
int n_test_times
Definition: findtimezone.c:149
const char * tm_zone
Definition: pgtime.h:37
bool pg_tz_acceptable(pg_tz *tz)
Definition: localtime.c:1839
Definition: pgtz.h:59
struct pg_tm * pg_localtime(const pg_time_t *timep, const pg_tz *tz)
Definition: localtime.c:1314
int tm_year
Definition: pgtime.h:32
int i
int tm_sec
Definition: pgtime.h:27
int tm_min
Definition: pgtime.h:28
const char * select_default_timezone ( const char *  share_path)

Definition at line 1375 of file findtimezone.c.

References identify_system_timezone(), snprintf(), tzdirpath, and validate_zone().

Referenced by setup_config().

1376 {
1377  const char *tzname;
1378 
1379  /* Initialize timezone directory path, if needed */
1380 #ifndef SYSTEMTZDIR
1381  snprintf(tzdirpath, sizeof(tzdirpath), "%s/timezone", share_path);
1382 #endif
1383 
1384  /* Check TZ environment variable */
1385  tzname = getenv("TZ");
1386  if (validate_zone(tzname))
1387  return tzname;
1388 
1389  /* Nope, so try to identify the system timezone */
1390  tzname = identify_system_timezone();
1391  if (validate_zone(tzname))
1392  return tzname;
1393 
1394  return NULL;
1395 }
static bool validate_zone(const char *tzname)
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
static char * share_path
Definition: initdb.c:119
static char tzdirpath[MAXPGPATH]
Definition: findtimezone.c:26
static const char * identify_system_timezone(void)
Definition: findtimezone.c:310
static bool validate_zone ( const char *  tzname)
static

Definition at line 1346 of file findtimezone.c.

References pg_load_tz(), and pg_tz_acceptable().

Referenced by select_default_timezone().

1347 {
1348  pg_tz *tz;
1349 
1350  if (!tzname || !tzname[0])
1351  return false;
1352 
1353  tz = pg_load_tz(tzname);
1354  if (!tz)
1355  return false;
1356 
1357  if (!pg_tz_acceptable(tz))
1358  return false;
1359 
1360  return true;
1361 }
static pg_tz * pg_load_tz(const char *name)
Definition: findtimezone.c:90
bool pg_tz_acceptable(pg_tz *tz)
Definition: localtime.c:1839
Definition: pgtz.h:59

Variable Documentation

char tzdirpath[MAXPGPATH]
static

Definition at line 26 of file findtimezone.c.

Referenced by pg_TZDIR(), and select_default_timezone().