From f3094920a567cde6c86adf36a1a033d7431b11ff Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 19 Oct 2016 18:55:52 -0400 Subject: Sync our copy of the timezone library with IANA release tzcode2016g. This is mostly to absorb some corner-case fixes in zic for year-2037 timestamps. The other changes that have been made are unlikely to affect our usage, but nonetheless we may as well take 'em. --- src/timezone/zic.c | 440 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 246 insertions(+), 194 deletions(-) (limited to 'src/timezone/zic.c') diff --git a/src/timezone/zic.c b/src/timezone/zic.c index b546a17372..52d8004ff7 100644 --- a/src/timezone/zic.c +++ b/src/timezone/zic.c @@ -105,7 +105,7 @@ static int addtype(zic_t, char const *, bool, bool, bool); static void leapadd(zic_t, bool, int, int); static void adjleap(void); static void associate(void); -static void dolink(const char *fromfield, const char *tofield); +static void dolink(const char *, const char *, bool); static char **getfields(char *buf); static zic_t gethms(const char *string, const char *errstring, bool); @@ -119,7 +119,7 @@ static bool inzsub(char **, int, bool); static int itsdir(const char *name); static bool is_alpha(char a); static char lowerit(char); -static bool mkdirs(char *); +static void mkdirs(char const *, bool); static void newabbr(const char *abbr); static zic_t oadd(zic_t t1, zic_t t2); static void outzone(const struct zone * zp, int ntzones); @@ -136,6 +136,15 @@ enum { PERCENT_Z_LEN_BOUND = sizeof "+995959" - 1}; +/* If true, work around a bug in Qt 5.6.1 and earlier, which mishandles + tz binary files whose POSIX-TZ-style strings contain '<'; see + QTBUG-53071 . This + workaround will no longer be needed when Qt 5.6.1 and earlier are + obsolete, say in the year 2021. */ +enum +{ +WORK_AROUND_QTBUG_53071 = true}; + static int charcnt; static bool errors; static bool warnings; @@ -346,6 +355,7 @@ static const int len_years[2] = { static struct attype { zic_t at; + bool dontmerge; unsigned char type; } *attypes; static zic_t gmtoffs[TZ_MAX_TYPES]; @@ -410,7 +420,8 @@ growalloc(void *ptr, size_t itemsize, int nitems, int *nitems_alloc) return ptr; else { - int amax = INT_MAX < SIZE_MAX ? INT_MAX : SIZE_MAX; + int nitems_max = INT_MAX - WORK_AROUND_QTBUG_53071; + int amax = nitems_max < SIZE_MAX ? nitems_max : SIZE_MAX; if ((amax - 1) / 3 * 2 < *nitems_alloc) memory_exhausted(_("int overflow")); @@ -478,17 +489,17 @@ warning(const char *string,...) } static void -close_file(FILE *stream, char const * name) +close_file(FILE *stream, char const * dir, char const * name) { char const *e = (ferror(stream) ? _("I/O error") : fclose(stream) != 0 ? strerror(errno) : NULL); if (e) { - fprintf(stderr, "%s: ", progname); - if (name) - fprintf(stderr, "%s: ", name); - fprintf(stderr, "%s\n", e); + fprintf(stderr, "%s: %s%s%s%s%s\n", progname, + dir ? dir : "", dir ? "/" : "", + name ? name : "", name ? ": " : "", + e); exit(EXIT_FAILURE); } } @@ -503,10 +514,34 @@ usage(FILE *stream, int status) "Report bugs to %s.\n"), progname, progname, PACKAGE_BUGREPORT); if (status == EXIT_SUCCESS) - close_file(stream, NULL); + close_file(stream, NULL, NULL); exit(status); } +/* Change the working directory to DIR, possibly creating DIR and its + ancestors. After this is done, all files are accessed with names + relative to DIR. */ +static void +change_directory(char const * dir) +{ + if (chdir(dir) != 0) + { + int chdir_errno = errno; + + if (chdir_errno == ENOENT) + { + mkdirs(dir, false); + chdir_errno = chdir(dir) == 0 ? 0 : errno; + } + if (chdir_errno != 0) + { + fprintf(stderr, _("%s: Can't chdir to %s: %s\n"), + progname, dir, strerror(chdir_errno)); + exit(EXIT_FAILURE); + } + } +} + static const char *psxrules; static const char *lcltime; static const char *directory; @@ -534,7 +569,7 @@ main(int argc, char *argv[]) if (strcmp(argv[i], "--version") == 0) { printf("zic %s\n", PG_VERSION); - close_file(stdout, NULL); + close_file(stdout, NULL, NULL); return EXIT_SUCCESS; } else if (strcmp(argv[i], "--help") == 0) @@ -630,6 +665,7 @@ main(int argc, char *argv[]) if (errors) return EXIT_FAILURE; associate(); + change_directory(directory); for (i = 0; i < nzones; i = j) { /* @@ -646,7 +682,7 @@ main(int argc, char *argv[]) for (i = 0; i < nlinks; ++i) { eat(links[i].l_filename, links[i].l_linenum); - dolink(links[i].l_from, links[i].l_to); + dolink(links[i].l_from, links[i].l_to, false); if (noise) for (j = 0; j < nlinks; ++j) if (strcmp(links[i].l_to, @@ -656,12 +692,12 @@ main(int argc, char *argv[]) if (lcltime != NULL) { eat(_("command line"), 1); - dolink(lcltime, TZDEFAULT); + dolink(lcltime, TZDEFAULT, true); } if (psxrules != NULL) { eat(_("command line"), 1); - dolink(psxrules, TZDEFRULES); + dolink(psxrules, TZDEFRULES, true); } if (warnings && (ferror(stderr) || fclose(stderr) != 0)) return EXIT_FAILURE; @@ -751,131 +787,117 @@ namecheck(const char *name) return componentcheck(name, component, cp); } -static char * -relname(char const * dir, char const * base) -{ - if (*base == '/') - return ecpyalloc(base); - else - { - size_t dir_len = strlen(dir); - bool needs_slash = dir_len && dir[dir_len - 1] != '/'; - char *result = emalloc(dir_len + needs_slash + strlen(base) + 1); - - result[dir_len] = '/'; - strcpy(result + dir_len + needs_slash, base); - return memcpy(result, dir, dir_len); - } -} - static void -dolink(char const * fromfield, char const * tofield) +dolink(char const * fromfield, char const * tofield, bool staysymlink) { - char *fromname; - char *toname; int fromisdir; - - fromname = relname(directory, fromfield); - toname = relname(directory, tofield); + bool todirs_made = false; + int link_errno; /* * We get to be careful here since there's a fair chance of root running * us. */ - fromisdir = itsdir(fromname); + fromisdir = itsdir(fromfield); if (fromisdir) { char const *e = strerror(fromisdir < 0 ? errno : EPERM); - fprintf(stderr, _("%s: link from %s failed: %s"), - progname, fromname, e); + fprintf(stderr, _("%s: link from %s/%s failed: %s\n"), + progname, directory, fromfield, e); exit(EXIT_FAILURE); } - if (link(fromname, toname) != 0) + if (staysymlink) + staysymlink = itsdir(tofield) == 2; + if (remove(tofield) == 0) + todirs_made = true; + else if (errno != ENOENT) { - int link_errno = errno; - bool retry_if_link_supported = false; + char const *e = strerror(errno); - if (link_errno == ENOENT || link_errno == ENOTSUP) + fprintf(stderr, _("%s: Can't remove %s/%s: %s\n"), + progname, directory, tofield, e); + exit(EXIT_FAILURE); + } + link_errno = (staysymlink ? ENOTSUP + : link(fromfield, tofield) == 0 ? 0 : errno); + if (link_errno == ENOENT && !todirs_made) + { + mkdirs(tofield, true); + todirs_made = true; + link_errno = link(fromfield, tofield) == 0 ? 0 : errno; + } + if (link_errno != 0) + { +#ifdef HAVE_SYMLINK + const char *s = fromfield; + const char *t; + char *p; + size_t dotdots = 0; + char *symlinkcontents; + int symlink_errno; + + do + t = s; + while ((s = strchr(s, '/')) + && strncmp(fromfield, tofield, ++s - fromfield) == 0); + + for (s = tofield + (t - fromfield); *s; s++) + dotdots += *s == '/'; + symlinkcontents = emalloc(3 * dotdots + strlen(t) + 1); + for (p = symlinkcontents; dotdots-- != 0; p += 3) + memcpy(p, "../", 3); + strcpy(p, t); + symlink_errno = symlink(symlinkcontents, tofield) == 0 ? 0 : errno; + if (symlink_errno == ENOENT && !todirs_made) { - if (!mkdirs(toname)) - exit(EXIT_FAILURE); - retry_if_link_supported = true; + mkdirs(tofield, true); + symlink_errno = symlink(symlinkcontents, tofield) == 0 ? 0 : errno; } - if ((link_errno == EEXIST || link_errno == ENOTSUP) - && itsdir(toname) == 0 - && (remove(toname) == 0 || errno == ENOENT)) - retry_if_link_supported = true; - if (retry_if_link_supported && link_errno != ENOTSUP) - link_errno = link(fromname, toname) == 0 ? 0 : errno; - if (link_errno != 0) + free(symlinkcontents); + if (symlink_errno == 0) { -#ifdef HAVE_SYMLINK - const char *s = fromfield; - const char *t; - char *p; - size_t dotdots = 0; - char *symlinkcontents; - int symlink_result; - - do - t = s; - while ((s = strchr(s, '/')) - && strncmp(fromfield, tofield, ++s - fromfield) == 0); - - for (s = tofield + (t - fromfield); *s; s++) - dotdots += *s == '/'; - symlinkcontents = emalloc(3 * dotdots + strlen(t) + 1); - for (p = symlinkcontents; dotdots-- != 0; p += 3) - memcpy(p, "../", 3); - strcpy(p, t); - symlink_result = symlink(symlinkcontents, toname); - free(symlinkcontents); - if (symlink_result == 0) - { - if (link_errno != ENOTSUP) - warning(_("symbolic link used because hard link failed: %s"), - strerror(link_errno)); - } - else + if (link_errno != ENOTSUP) + warning(_("symbolic link used because hard link failed: %s"), + strerror(link_errno)); + } + else #endif /* HAVE_SYMLINK */ - { - FILE *fp, - *tp; - int c; + { + FILE *fp, + *tp; + int c; - fp = fopen(fromname, "rb"); - if (!fp) - { - const char *e = strerror(errno); + fp = fopen(fromfield, "rb"); + if (!fp) + { + char const *e = strerror(errno); - fprintf(stderr, - _("%s: Can't read %s: %s\n"), - progname, fromname, e); - exit(EXIT_FAILURE); - } - tp = fopen(toname, "wb"); - if (!tp) - { - const char *e = strerror(errno); + fprintf(stderr, _("%s: Can't read %s/%s: %s\n"), + progname, directory, fromfield, e); + exit(EXIT_FAILURE); + } + tp = fopen(tofield, "wb"); + if (!tp) + { + char const *e = strerror(errno); - fprintf(stderr, - _("%s: Can't create %s: %s\n"), - progname, toname, e); - exit(EXIT_FAILURE); - } - while ((c = getc(fp)) != EOF) - putc(c, tp); - close_file(fp, fromname); - close_file(tp, toname); - if (link_errno != ENOTSUP) - warning(_("copy used because hard link failed: %s"), - strerror(link_errno)); + fprintf(stderr, _("%s: Can't create %s/%s: %s\n"), + progname, directory, tofield, e); + exit(EXIT_FAILURE); } + while ((c = getc(fp)) != EOF) + putc(c, tp); + close_file(fp, directory, fromfield); + close_file(tp, directory, tofield); + if (link_errno != ENOTSUP) + warning(_("copy used because hard link failed: %s"), + strerror(link_errno)); + else if (symlink_errno != ENOTSUP) + warning(_("copy used because symbolic link failed: %s"), + strerror(symlink_errno)); } } - free(fromname); - free(toname); } #define TIME_T_BITS_IN_FILE 64 @@ -888,10 +910,6 @@ static zic_t const max_time = MAXVAL(zic_t, TIME_T_BITS_IN_FILE); * rounded downward to the negation of a power of two that is * comfortably outside the error bounds. * - * zic does not output time stamps before this, partly because they - * are physically suspect, and partly because GNOME mishandles them; see - * GNOME bug 730332 . - * * For the time of the Big Bang, see: * * Ade PAR, Aghanim N, Armitage-Caplan C et al. Planck 2013 results. @@ -913,26 +931,45 @@ static zic_t const max_time = MAXVAL(zic_t, TIME_T_BITS_IN_FILE); #define BIG_BANG (- (((zic_t) 1) << 59)) #endif -static const zic_t big_bang_time = BIG_BANG; +/* If true, work around GNOME bug 730332 + + by refusing to output time stamps before BIG_BANG. + Such time stamps are physically suspect anyway. -/* Return 1 if NAME is a directory, 0 if it's something else, -1 if trouble. */ + The GNOME bug is scheduled to be fixed in GNOME 3.22, and if so + this workaround will no longer be needed when GNOME 3.21 and + earlier are obsolete, say in the year 2021. */ +enum +{ +WORK_AROUND_GNOME_BUG_730332 = true}; + +static const zic_t early_time = (WORK_AROUND_GNOME_BUG_730332 + ? BIG_BANG + : MINVAL(zic_t, TIME_T_BITS_IN_FILE)); + +/* Return 1 if NAME is a directory, 2 if a symbolic link, 0 if + something else, -1 (setting errno) if trouble. */ static int itsdir(char const * name) { struct stat st; - int res = stat(name, &st); + int res = lstat(name, &st); -#ifdef S_ISDIR if (res == 0) - return S_ISDIR(st.st_mode) != 0; -#endif - if (res == 0 || errno == EOVERFLOW) { - char *nameslashdot = relname(name, "."); - bool dir = stat(nameslashdot, &st) == 0 || errno == EOVERFLOW; +#ifdef S_ISDIR + return S_ISDIR(st.st_mode) ? 1 : S_ISLNK(st.st_mode) ? 2 : 0; +#else + size_t n = strlen(name); + char *nameslashdot = emalloc(n + 3); + bool dir; + memcpy(nameslashdot, name, n); + strcpy(&nameslashdot[n], &"/."[!(n && name[n - 1] != '/')]); + dir = lstat(nameslashdot, &st) == 0; free(nameslashdot); return dir; +#endif } return -1; } @@ -1129,7 +1166,7 @@ infile(const char *name) } free(fields); } - close_file(fp, filename); + close_file(fp, NULL, filename); if (wantcont) error(_("expected continuation line not found")); } @@ -1313,7 +1350,7 @@ inzsub(char **fields, int nfields, bool iscont) z.z_filename = filename; z.z_linenum = linenum; z.z_gmtoff = gethms(fields[i_gmtoff], _("invalid UT offset"), true); - if ((cp = strchr(fields[i_format], '%')) != 0) + if ((cp = strchr(fields[i_format], '%')) != NULL) { if ((*++cp != 's' && *cp != 'z') || strchr(cp, '%') || strchr(fields[i_format], '/')) @@ -1491,7 +1528,7 @@ inleap(char **fields, int nfields) return; } t = tadd(t, tod); - if (t < big_bang_time) + if (t < early_time) { error(_("leap second precedes Big Bang")); return; @@ -1764,11 +1801,14 @@ writezone(const char *const name, const char *const string, char version) int timecnt32, timei32; int pass; - char *fullname; static const struct tzhead tzh0; static struct tzhead tzh; - zic_t *ats = emalloc(size_product(timecnt, sizeof *ats + 1)); - void *typesptr = ats + timecnt; + bool dir_checked = false; + zic_t one = 1; + zic_t y2038_boundary = one << 31; + int nats = timecnt + WORK_AROUND_QTBUG_53071; + zic_t *ats = emalloc(size_product(nats, sizeof *ats + 1)); + void *typesptr = ats + nats; unsigned char *types = typesptr; /* @@ -1786,7 +1826,7 @@ writezone(const char *const name, const char *const string, char version) toi = 0; fromi = 0; - while (fromi < timecnt && attypes[fromi].at < big_bang_time) + while (fromi < timecnt && attypes[fromi].at < early_time) ++fromi; for (; fromi < timecnt; ++fromi) { @@ -1799,8 +1839,9 @@ writezone(const char *const name, const char *const string, char version) attypes[fromi].type; continue; } - if (toi == 0 || - attypes[toi - 1].type != attypes[fromi].type) + if (toi == 0 + || attypes[fromi].dontmerge + || attypes[toi - 1].type != attypes[fromi].type) attypes[toi++] = attypes[fromi]; } timecnt = toi; @@ -1818,6 +1859,20 @@ writezone(const char *const name, const char *const string, char version) types[i] = attypes[i].type; } + /* + * Work around QTBUG-53071 for time stamps less than y2038_boundary - 1, + * by inserting a no-op transition at time y2038_boundary - 1. This works + * only for timestamps before the boundary, which should be good enough in + * practice as QTBUG-53071 should be long-dead by 2038. + */ + if (WORK_AROUND_QTBUG_53071 && timecnt != 0 + && ats[timecnt - 1] < y2038_boundary - 1 && strchr(string, '<')) + { + ats[timecnt] = y2038_boundary - 1; + types[timecnt] = types[timecnt - 1]; + timecnt++; + } + /* * Correct for leap seconds. */ @@ -1862,29 +1917,35 @@ writezone(const char *const name, const char *const string, char version) --leapcnt32; ++leapi32; } - fullname = relname(directory, name); /* * Remove old file, if any, to snap links. */ - if (itsdir(fullname) == 0 && remove(fullname) != 0 && errno != ENOENT) + if (remove(name) == 0) + dir_checked = true; + else if (errno != ENOENT) { const char *e = strerror(errno); - fprintf(stderr, _("%s: Cannot remove %s: %s\n"), - progname, fullname, e); + fprintf(stderr, _("%s: Cannot remove %s/%s: %s\n"), + progname, directory, name, e); exit(EXIT_FAILURE); } - if ((fp = fopen(fullname, "wb")) == NULL) + fp = fopen(name, "wb"); + if (!fp) { - if (!mkdirs(fullname)) - exit(EXIT_FAILURE); - if ((fp = fopen(fullname, "wb")) == NULL) - { - const char *e = strerror(errno); + int fopen_errno = errno; - fprintf(stderr, _("%s: Cannot create %s: %s\n"), - progname, fullname, e); + if (fopen_errno == ENOENT && !dir_checked) + { + mkdirs(name, true); + fp = fopen(name, "wb"); + fopen_errno = errno; + } + if (!fp) + { + fprintf(stderr, _("%s: Cannot create %s/%s: %s\n"), + progname, directory, name, strerror(fopen_errno)); exit(EXIT_FAILURE); } } @@ -2130,9 +2191,8 @@ writezone(const char *const name, const char *const string, char version) putc(ttisgmts[i], fp); } fprintf(fp, "\n%s\n", string); - close_file(fp, fullname); + close_file(fp, directory, name); free(ats); - free(fullname); } static char const * @@ -2527,6 +2587,7 @@ outzone(const struct zone * zpfirst, int zonecount) int compat; bool do_extend; char version; + int lastatmax = -1; max_abbr_len = 2 + max_format_len + max_abbrvar_len; max_envvar_len = 2 * max_abbr_len + 5 * 9; @@ -2649,9 +2710,9 @@ outzone(const struct zone * zpfirst, int zonecount) */ stdoff = 0; zp = &zpfirst[i]; - usestart = i > 0 && (zp - 1)->z_untiltime > big_bang_time; + usestart = i > 0 && (zp - 1)->z_untiltime > early_time; useuntil = i < (zonecount - 1); - if (useuntil && zp->z_untiltime <= big_bang_time) + if (useuntil && zp->z_untiltime <= early_time) continue; gmtoff = zp->z_gmtoff; eat(zp->z_filename, zp->z_linenum); @@ -2670,7 +2731,7 @@ outzone(const struct zone * zpfirst, int zonecount) usestart = false; } else - addtt(big_bang_time, type); + addtt(early_time, type); } else for (year = min_year; year <= max_year; ++year) @@ -2792,6 +2853,10 @@ outzone(const struct zone * zpfirst, int zonecount) offset = oadd(zp->z_gmtoff, rp->r_stdoff); type = addtype(offset, ab, rp->r_stdoff != 0, rp->r_todisstd, rp->r_todisgmt); + if (rp->r_hiyear == ZIC_MAX + && !(0 <= lastatmax + && ktime < attypes[lastatmax].at)) + lastatmax = timecnt; addtt(ktime, type); } } @@ -2827,6 +2892,8 @@ outzone(const struct zone * zpfirst, int zonecount) starttime = tadd(starttime, -gmtoff); } } + if (0 <= lastatmax) + attypes[lastatmax].dontmerge = true; if (do_extend) { /* @@ -2850,22 +2917,8 @@ outzone(const struct zone * zpfirst, int zonecount) lastat = &attypes[i]; if (lastat->at < rpytime(&xr, max_year - 1)) { - /* - * Create new type code for the redundant entry, to prevent it - * being optimized away. - */ - if (typecnt >= TZ_MAX_TYPES) - { - error(_("too many local time types")); - exit(EXIT_FAILURE); - } - gmtoffs[typecnt] = gmtoffs[lastat->type]; - isdsts[typecnt] = isdsts[lastat->type]; - ttisstds[typecnt] = ttisstds[lastat->type]; - ttisgmts[typecnt] = ttisgmts[lastat->type]; - abbrinds[typecnt] = abbrinds[lastat->type]; - ++typecnt; addtt(rpytime(&xr, max_year + 1), typecnt - 1); + attypes[timecnt - 1].dontmerge = true; } } writezone(zpfirst->z_name, envvar, version); @@ -2877,8 +2930,8 @@ outzone(const struct zone * zpfirst, int zonecount) static void addtt(zic_t starttime, int type) { - if (starttime <= big_bang_time || - (timecnt == 1 && attypes[0].at < big_bang_time)) + if (starttime <= early_time + || (timecnt == 1 && attypes[0].at < early_time)) { gmtoffs[0] = gmtoffs[type]; isdsts[0] = isdsts[type]; @@ -2894,6 +2947,7 @@ addtt(zic_t starttime, int type) } attypes = growalloc(attypes, sizeof *attypes, timecnt, &timecnt_alloc); attypes[timecnt].at = starttime; + attypes[timecnt].dontmerge = false; attypes[timecnt].type = type; ++timecnt; } @@ -3441,53 +3495,51 @@ newabbr(const char *string) charcnt += i; } -static bool -mkdirs(char *argname) +/* Ensure that the directories of ARGNAME exist, by making any missing + ones. If ANCESTORS, do this only for ARGNAME's ancestors; otherwise, + do it for ARGNAME too. Exit with failure if there is trouble. */ +static void +mkdirs(char const * argname, bool ancestors) { char *name; char *cp; - if (argname == NULL || *argname == '\0') - return true; cp = name = ecpyalloc(argname); - while ((cp = strchr(cp + 1, '/')) != NULL) - { - *cp = '\0'; + + /* Do not mkdir a root directory, as it must exist. */ #ifdef WIN32 + if (is_alpha(name[0]) && name[1] == ':') + cp += 2; +#endif + while (*cp == '/') + cp++; - /* - * DOS drive specifier? - */ - if (is_alpha(name[0]) && name[1] == ':' && name[2] == '\0') - { - *cp = '/'; - continue; - } -#endif /* WIN32 */ + while (cp && ((cp = strchr(cp, '/')) || !ancestors)) + { + if (cp) + *cp = '\0'; /* * Try to create it. It's OK if creation fails because the directory * already exists, perhaps because some other process just created it. + * For simplicity do not check first whether it already exists, as + * that is checked anyway if the mkdir fails. */ if (mkdir(name, MKDIR_UMASK) != 0) { int err = errno; - if (itsdir(name) <= 0) + if (err != EEXIST && itsdir(name) < 0) { - char const *e = strerror(err); - - warning(_("%s: Can't create directory" - " %s: %s"), - progname, name, e); - free(name); - return false; + error(_("%s: Cannot create directory %s: %s"), + progname, name, strerror(err)); + exit(EXIT_FAILURE); } } - *cp = '/'; + if (cp) + *cp++ = '/'; } free(name); - return true; } -- cgit v1.2.3 From ad90ac4d671d320ade3c127f215e97cd49c307fb Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 19 Oct 2016 19:28:11 -0400 Subject: Windows portability fix. Per buildfarm. --- src/timezone/zic.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/timezone/zic.c') diff --git a/src/timezone/zic.c b/src/timezone/zic.c index 52d8004ff7..04f4df27ce 100644 --- a/src/timezone/zic.c +++ b/src/timezone/zic.c @@ -35,6 +35,9 @@ typedef int64 zic_t; #define MKDIR_UMASK 0755 #endif #endif +#ifndef S_ISLNK +#define S_ISLNK(m) 0 +#endif struct rule { -- cgit v1.2.3 From 23ed2ba8121178474f8c51774c6c258cb165a562 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 19 Oct 2016 23:32:08 -0400 Subject: Another portability fix for tzcode2016g update. clang points out that SIZE_MAX wouldn't fit into an int, which means this comparison is pretty useless. Per report from Thomas Munro. --- src/timezone/zic.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/timezone/zic.c') diff --git a/src/timezone/zic.c b/src/timezone/zic.c index 04f4df27ce..3f714ef46c 100644 --- a/src/timezone/zic.c +++ b/src/timezone/zic.c @@ -424,9 +424,8 @@ growalloc(void *ptr, size_t itemsize, int nitems, int *nitems_alloc) else { int nitems_max = INT_MAX - WORK_AROUND_QTBUG_53071; - int amax = nitems_max < SIZE_MAX ? nitems_max : SIZE_MAX; - if ((amax - 1) / 3 * 2 < *nitems_alloc) + if ((nitems_max - 1) / 3 * 2 < *nitems_alloc) memory_exhausted(_("int overflow")); *nitems_alloc = *nitems_alloc + (*nitems_alloc >> 1) + 1; return erealloc(ptr, size_product(*nitems_alloc, itemsize)); -- cgit v1.2.3 From 5e21b6811148fdc1fce9dcdcdc777418cc901fe4 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 20 Oct 2016 15:40:07 -0400 Subject: Sync our copy of the timezone library with IANA release tzcode2016h. This absorbs a fix for a symlink-manipulation bug in zic that was introduced in 2016g. It probably isn't interesting for our use-case, but I'm not quite sure, so let's update while we're at it. --- src/timezone/zic.c | 76 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 20 deletions(-) (limited to 'src/timezone/zic.c') diff --git a/src/timezone/zic.c b/src/timezone/zic.c index 3f714ef46c..d624b23a8e 100644 --- a/src/timezone/zic.c +++ b/src/timezone/zic.c @@ -789,6 +789,56 @@ namecheck(const char *name) return componentcheck(name, component, cp); } +/* + * Create symlink contents suitable for symlinking FROM to TO, as a + * freshly allocated string. FROM should be a relative file name, and + * is relative to the global variable DIRECTORY. TO can be either + * relative or absolute. + */ +#ifdef HAVE_SYMLINK +static char * +relname(char const * from, char const * to) +{ + size_t i, + taillen, + dotdotetcsize; + size_t dir_len = 0, + dotdots = 0, + linksize = SIZE_MAX; + char const *f = from; + char *result = NULL; + + if (*to == '/') + { + /* Make F absolute too. */ + size_t len = strlen(directory); + bool needslash = len && directory[len - 1] != '/'; + + linksize = len + needslash + strlen(from) + 1; + f = result = emalloc(linksize); + strcpy(result, directory); + result[len] = '/'; + strcpy(result + len + needslash, from); + } + for (i = 0; f[i] && f[i] == to[i]; i++) + if (f[i] == '/') + dir_len = i + 1; + for (; f[i]; i++) + dotdots += f[i] == '/' && f[i - 1] != '/'; + taillen = i - dir_len; + dotdotetcsize = 3 * dotdots + taillen + 1; + if (dotdotetcsize <= linksize) + { + if (!result) + result = emalloc(dotdotetcsize); + for (i = 0; i < dotdots; i++) + memcpy(result + 3 * i, "../", 3); + memmove(result + 3 * dotdots, f + dir_len, taillen + 1); + } + return result; +} +#endif /* HAVE_SYMLINK */ + static void dolink(char const * fromfield, char const * tofield, bool staysymlink) { @@ -832,31 +882,17 @@ dolink(char const * fromfield, char const * tofield, bool staysymlink) if (link_errno != 0) { #ifdef HAVE_SYMLINK - const char *s = fromfield; - const char *t; - char *p; - size_t dotdots = 0; - char *symlinkcontents; - int symlink_errno; + bool absolute = *fromfield == '/'; + char *linkalloc = absolute ? NULL : relname(fromfield, tofield); + char const *contents = absolute ? fromfield : linkalloc; + int symlink_errno = symlink(contents, tofield) == 0 ? 0 : errno; - do - t = s; - while ((s = strchr(s, '/')) - && strncmp(fromfield, tofield, ++s - fromfield) == 0); - - for (s = tofield + (t - fromfield); *s; s++) - dotdots += *s == '/'; - symlinkcontents = emalloc(3 * dotdots + strlen(t) + 1); - for (p = symlinkcontents; dotdots-- != 0; p += 3) - memcpy(p, "../", 3); - strcpy(p, t); - symlink_errno = symlink(symlinkcontents, tofield) == 0 ? 0 : errno; if (symlink_errno == ENOENT && !todirs_made) { mkdirs(tofield, true); - symlink_errno = symlink(symlinkcontents, tofield) == 0 ? 0 : errno; + symlink_errno = symlink(contents, tofield) == 0 ? 0 : errno; } - free(symlinkcontents); + free(linkalloc); if (symlink_errno == 0) { if (link_errno != ENOTSUP) -- cgit v1.2.3 From 19b2094d96807e43d29687b3860e8fffb9da61b4 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 26 Oct 2016 13:40:41 -0400 Subject: Fix not-HAVE_SYMLINK code in zic.c. I broke this in commit f3094920a. Apparently it's dead code anyway, at least as far as our buildfarm is concerned (and the upstream IANA code doesn't worry at all about symlink() not being present). But as long as the rest of our code is willing to guard against not having symlink(), this should too. Noted while investigating a tangentially-related complaint from Sandeep Thakkar. Back-patch to keep branches in sync. --- src/timezone/zic.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/timezone/zic.c') diff --git a/src/timezone/zic.c b/src/timezone/zic.c index d624b23a8e..64adb6bd46 100644 --- a/src/timezone/zic.c +++ b/src/timezone/zic.c @@ -931,9 +931,11 @@ dolink(char const * fromfield, char const * tofield, bool staysymlink) if (link_errno != ENOTSUP) warning(_("copy used because hard link failed: %s"), strerror(link_errno)); +#ifdef HAVE_SYMLINK else if (symlink_errno != ENOTSUP) warning(_("copy used because symbolic link failed: %s"), strerror(symlink_errno)); +#endif } } } -- cgit v1.2.3 From 1f87181e12beb067d21b79493393edcff14c190b Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 3 Nov 2016 22:24:34 -0400 Subject: Sync our copy of the timezone library with IANA tzcode master. This patch absorbs some unreleased fixes for symlink manipulation bugs introduced in tzcode 2016g. Ordinarily I'd wait around for a released version, but in this case it seems like we could do with extra testing, in particular checking whether it works in EDB's VMware build environment. This corresponds to commit aec59156abbf8472ba201b6c7ca2592f9c10e077 in https://github.com/eggert/tz. Per a report from Sandeep Thakkar, building in an environment where hard links are not supported in the timezone data installation directory failed, because upstream code refactoring had broken the case of symlinking from an existing symlink. Further experimentation also showed that the symlinks were sometimes made incorrectly, with too many or too few "../"'s in the symlink contents. This should get back-patched, but first let's see what the buildfarm makes of it. I'm not too sure about the new dependency on linkat(2). Report: Discussion: http://mm.icann.org/pipermail/tz/2016-November/024431.html --- src/timezone/zic.c | 284 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 176 insertions(+), 108 deletions(-) (limited to 'src/timezone/zic.c') diff --git a/src/timezone/zic.c b/src/timezone/zic.c index 64adb6bd46..7da95aad53 100644 --- a/src/timezone/zic.c +++ b/src/timezone/zic.c @@ -8,9 +8,11 @@ #include "postgres_fe.h" +#include #include #include #include +#include #include "pg_getopt.h" @@ -35,14 +37,24 @@ typedef int64 zic_t; #define MKDIR_UMASK 0755 #endif #endif -#ifndef S_ISLNK -#define S_ISLNK(m) 0 +#ifndef AT_SYMLINK_FOLLOW +#define linkat(fromdir, from, todir, to, flag) \ + (itssymlink(from) ? (errno = ENOTSUP, -1) : link(from, to)) #endif +/* The maximum ptrdiff_t value, for pre-C99 platforms. */ +#ifndef PTRDIFF_MAX +static ptrdiff_t const PTRDIFF_MAX = MAXVAL(ptrdiff_t, TYPE_BIT(ptrdiff_t)); +#endif + +/* The type and printf format for line numbers. */ +typedef int lineno; +#define PRIdLINENO "d" + struct rule { const char *r_filename; - int r_linenum; + lineno r_linenum; const char *r_name; zic_t r_loyear; /* for example, 1986 */ @@ -64,7 +76,7 @@ struct rule zic_t r_stdoff; /* offset from standard time */ const char *r_abbrvar; /* variable part of abbreviation */ - int r_todo; /* a rule to do (used in outzone) */ + bool r_todo; /* a rule to do (used in outzone) */ zic_t r_temp; /* used in outzone */ }; @@ -79,7 +91,7 @@ struct rule struct zone { const char *z_filename; - int z_linenum; + lineno z_linenum; const char *z_name; zic_t z_gmtoff; @@ -90,7 +102,7 @@ struct zone zic_t z_stdoff; struct rule *z_rules; - int z_nrules; + ptrdiff_t z_nrules; struct rule z_untilrule; zic_t z_untiltime; @@ -119,20 +131,21 @@ static void inrule(char **fields, int nfields); static bool inzcont(char **fields, int nfields); static bool inzone(char **fields, int nfields); static bool inzsub(char **, int, bool); -static int itsdir(const char *name); +static bool itsdir(char const *); +static bool itssymlink(char const *); static bool is_alpha(char a); static char lowerit(char); static void mkdirs(char const *, bool); static void newabbr(const char *abbr); static zic_t oadd(zic_t t1, zic_t t2); -static void outzone(const struct zone * zp, int ntzones); +static void outzone(const struct zone * zp, ptrdiff_t ntzones); static zic_t rpytime(const struct rule * rp, zic_t wantedy); static void rulesub(struct rule * rp, const char *loyearp, const char *hiyearp, const char *typep, const char *monthp, const char *dayp, const char *timep); static zic_t tadd(zic_t t1, zic_t t2); -static bool yearistype(int year, const char *type); +static bool yearistype(zic_t year, const char *type); /* Bound on length of what %z can expand to. */ enum @@ -156,7 +169,7 @@ static int leapcnt; static bool leapseen; static zic_t leapminyear; static zic_t leapmaxyear; -static int linenum; +static lineno linenum; static int max_abbrvar_len = PERCENT_Z_LEN_BOUND; static int max_format_len; static zic_t max_year; @@ -165,10 +178,10 @@ static bool noise; static bool print_abbrevs; static zic_t print_cutoff; static const char *rfilename; -static int rlinenum; +static lineno rlinenum; static const char *progname; -static int timecnt; -static int timecnt_alloc; +static ptrdiff_t timecnt; +static ptrdiff_t timecnt_alloc; static int typecnt; /* @@ -253,24 +266,24 @@ static int typecnt; #define YR_ONLY 2 static struct rule *rules; -static int nrules; /* number of rules */ -static int nrules_alloc; +static ptrdiff_t nrules; /* number of rules */ +static ptrdiff_t nrules_alloc; static struct zone *zones; -static int nzones; /* number of zones */ -static int nzones_alloc; +static ptrdiff_t nzones; /* number of zones */ +static ptrdiff_t nzones_alloc; struct link { const char *l_filename; - int l_linenum; + lineno l_linenum; const char *l_from; const char *l_to; }; static struct link *links; -static int nlinks; -static int nlinks_alloc; +static ptrdiff_t nlinks; +static ptrdiff_t nlinks_alloc; struct lookup { @@ -417,17 +430,18 @@ ecpyalloc(char const * str) } static void * -growalloc(void *ptr, size_t itemsize, int nitems, int *nitems_alloc) +growalloc(void *ptr, size_t itemsize, ptrdiff_t nitems, ptrdiff_t * nitems_alloc) { if (nitems < *nitems_alloc) return ptr; else { - int nitems_max = INT_MAX - WORK_AROUND_QTBUG_53071; + ptrdiff_t nitems_max = PTRDIFF_MAX - WORK_AROUND_QTBUG_53071; + ptrdiff_t amax = nitems_max < SIZE_MAX ? nitems_max : SIZE_MAX; - if ((nitems_max - 1) / 3 * 2 < *nitems_alloc) - memory_exhausted(_("int overflow")); - *nitems_alloc = *nitems_alloc + (*nitems_alloc >> 1) + 1; + if ((amax - 1) / 3 * 2 < *nitems_alloc) + memory_exhausted(_("integer overflow")); + *nitems_alloc += (*nitems_alloc >> 1) + 1; return erealloc(ptr, size_product(*nitems_alloc, itemsize)); } } @@ -437,7 +451,7 @@ growalloc(void *ptr, size_t itemsize, int nitems, int *nitems_alloc) */ static void -eats(const char *name, int num, const char *rname, int rnum) +eats(char const * name, lineno num, char const * rname, lineno rnum) { filename = name; linenum = num; @@ -446,7 +460,7 @@ eats(const char *name, int num, const char *rname, int rnum) } static void -eat(const char *name, int num) +eat(char const * name, lineno num) { eats(name, num, NULL, -1); } @@ -459,10 +473,10 @@ verror(const char *string, va_list args) * "*" -v on BSD systems. */ if (filename) - fprintf(stderr, _("\"%s\", line %d: "), filename, linenum); + fprintf(stderr, _("\"%s\", line %" PRIdLINENO ": "), filename, linenum); vfprintf(stderr, string, args); if (rfilename != NULL) - fprintf(stderr, _(" (rule from \"%s\", line %d)"), + fprintf(stderr, _(" (rule from \"%s\", line %" PRIdLINENO ")"), rfilename, rlinenum); fprintf(stderr, "\n"); } @@ -553,9 +567,10 @@ static const char *yitcommand; int main(int argc, char *argv[]) { - int i; - int j; - int c; + int c, + k; + ptrdiff_t i, + j; #ifndef WIN32 umask(umask(S_IWGRP | S_IWOTH) | (S_IWGRP | S_IWOTH)); @@ -567,14 +582,14 @@ main(int argc, char *argv[]) _("wild compilation-time specification of zic_t")); return EXIT_FAILURE; } - for (i = 1; i < argc; ++i) - if (strcmp(argv[i], "--version") == 0) + for (k = 1; k < argc; k++) + if (strcmp(argv[k], "--version") == 0) { printf("zic %s\n", PG_VERSION); close_file(stdout, NULL, NULL); return EXIT_SUCCESS; } - else if (strcmp(argv[i], "--help") == 0) + else if (strcmp(argv[k], "--help") == 0) { usage(stdout, EXIT_SUCCESS); } @@ -662,8 +677,8 @@ main(int argc, char *argv[]) adjleap(); } - for (i = optind; i < argc; ++i) - infile(argv[i]); + for (k = optind; k < argc; k++) + infile(argv[k]); if (errors) return EXIT_FAILURE; associate(); @@ -713,7 +728,7 @@ componentcheck(char const * name, char const * component, enum { component_len_max = 14}; - size_t component_len = component_end - component; + ptrdiff_t component_len = component_end - component; if (component_len == 0) { @@ -731,8 +746,10 @@ componentcheck(char const * name, char const * component, if (0 < component_len && component_len <= 2 && component[0] == '.' && component_end[-1] == '.') { + int len = component_len; + error(_("file name '%s' contains '%.*s' component"), - name, (int) component_len, component); + name, len, component); return false; } if (noise) @@ -823,9 +840,9 @@ relname(char const * from, char const * to) for (i = 0; f[i] && f[i] == to[i]; i++) if (f[i] == '/') dir_len = i + 1; - for (; f[i]; i++) - dotdots += f[i] == '/' && f[i - 1] != '/'; - taillen = i - dir_len; + for (; to[i]; i++) + dotdots += to[i] == '/' && to[i - 1] != '/'; + taillen = strlen(f + dir_len); dotdotetcsize = 3 * dotdots + taillen + 1; if (dotdotetcsize <= linksize) { @@ -839,10 +856,19 @@ relname(char const * from, char const * to) } #endif /* HAVE_SYMLINK */ +/* Hard link FROM to TO, following any symbolic links. + Return 0 if successful, an error number otherwise. */ +static int +hardlinkerr(char const * from, char const * to) +{ + int r = linkat(AT_FDCWD, from, AT_FDCWD, to, AT_SYMLINK_FOLLOW); + + return r == 0 ? 0 : errno; +} + static void dolink(char const * fromfield, char const * tofield, bool staysymlink) { - int fromisdir; bool todirs_made = false; int link_errno; @@ -850,17 +876,14 @@ dolink(char const * fromfield, char const * tofield, bool staysymlink) * We get to be careful here since there's a fair chance of root running * us. */ - fromisdir = itsdir(fromfield); - if (fromisdir) + if (itsdir(fromfield)) { - char const *e = strerror(fromisdir < 0 ? errno : EPERM); - fprintf(stderr, _("%s: link from %s/%s failed: %s\n"), - progname, directory, fromfield, e); + progname, directory, fromfield, strerror(EPERM)); exit(EXIT_FAILURE); } if (staysymlink) - staysymlink = itsdir(tofield) == 2; + staysymlink = itssymlink(tofield); if (remove(tofield) == 0) todirs_made = true; else if (errno != ENOENT) @@ -871,13 +894,12 @@ dolink(char const * fromfield, char const * tofield, bool staysymlink) progname, directory, tofield, e); exit(EXIT_FAILURE); } - link_errno = (staysymlink ? ENOTSUP - : link(fromfield, tofield) == 0 ? 0 : errno); + link_errno = staysymlink ? ENOTSUP : hardlinkerr(fromfield, tofield); if (link_errno == ENOENT && !todirs_made) { mkdirs(tofield, true); todirs_made = true; - link_errno = link(fromfield, tofield) == 0 ? 0 : errno; + link_errno = hardlinkerr(fromfield, tofield); } if (link_errno != 0) { @@ -987,31 +1009,42 @@ static const zic_t early_time = (WORK_AROUND_GNOME_BUG_730332 ? BIG_BANG : MINVAL(zic_t, TIME_T_BITS_IN_FILE)); -/* Return 1 if NAME is a directory, 2 if a symbolic link, 0 if - something else, -1 (setting errno) if trouble. */ -static int +/* Return true if NAME is a directory. */ +static bool itsdir(char const * name) { struct stat st; - int res = lstat(name, &st); - + int res = stat(name, &st); +#ifdef S_ISDIR if (res == 0) + return S_ISDIR(st.st_mode) != 0; +#endif + if (res == 0 || errno == EOVERFLOW) { -#ifdef S_ISDIR - return S_ISDIR(st.st_mode) ? 1 : S_ISLNK(st.st_mode) ? 2 : 0; -#else size_t n = strlen(name); char *nameslashdot = emalloc(n + 3); bool dir; memcpy(nameslashdot, name, n); strcpy(&nameslashdot[n], &"/."[!(n && name[n - 1] != '/')]); - dir = lstat(nameslashdot, &st) == 0; + dir = stat(nameslashdot, &st) == 0 || errno == EOVERFLOW; free(nameslashdot); return dir; -#endif } - return -1; + return false; +} + +/* Return true if NAME is a symbolic link. */ +static bool +itssymlink(char const * name) +{ +#ifdef HAVE_SYMLINK + char c; + + return 0 <= readlink(name, &c, 1); +#else + return false; +#endif } /* @@ -1034,10 +1067,10 @@ associate(void) { struct zone *zp; struct rule *rp; - int base, + ptrdiff_t i, + j, + base, out; - int i, - j; if (nrules != 0) { @@ -1124,7 +1157,7 @@ infile(const char *name) const struct lookup *lp; int nfields; bool wantcont; - int num; + lineno num; char buf[BUFSIZ]; if (strcmp(name, "-") == 0) @@ -1175,7 +1208,7 @@ infile(const char *name) if (lp == NULL) error(_("input line of unknown type")); else - switch ((int) (lp->l_value)) + switch (lp->l_value) { case LC_RULE: inrule(fields, nfields); @@ -1302,7 +1335,7 @@ inrule(char **fields, int nfields) static bool inzone(char **fields, int nfields) { - int i; + ptrdiff_t i; if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS) { @@ -1327,8 +1360,8 @@ inzone(char **fields, int nfields) if (zones[i].z_name != NULL && strcmp(zones[i].z_name, fields[ZF_NAME]) == 0) { - error( - _("duplicate zone name %s (file \"%s\", line %d)"), + error(_("duplicate zone name %s" + " (file \"%s\", line %" PRIdLINENO ")"), fields[ZF_NAME], zones[i].z_filename, zones[i].z_linenum); @@ -1452,7 +1485,7 @@ inleap(char **fields, int nfields) { const char *cp; const struct lookup *lp; - int i, + zic_t i, j; /* PG: make year be int not zic_t to avoid sscanf portability issues */ @@ -1659,7 +1692,7 @@ rulesub(struct rule * rp, const char *loyearp, const char *hiyearp, lp = byword(cp, begin_years); rp->r_lowasnum = lp == NULL; if (!rp->r_lowasnum) - switch ((int) lp->l_value) + switch (lp->l_value) { case YR_MINIMUM: rp->r_loyear = ZIC_MIN; @@ -1684,7 +1717,7 @@ rulesub(struct rule * rp, const char *loyearp, const char *hiyearp, lp = byword(cp, end_years); rp->r_hiwasnum = lp == NULL; if (!rp->r_hiwasnum) - switch ((int) lp->l_value) + switch (lp->l_value) { case YR_MINIMUM: rp->r_hiyear = ZIC_MIN; @@ -1834,11 +1867,11 @@ static void writezone(const char *const name, const char *const string, char version) { FILE *fp; - int i, + ptrdiff_t i, j; int leapcnt32, leapi32; - int timecnt32, + ptrdiff_t timecnt32, timei32; int pass; static const struct tzhead tzh0; @@ -1846,7 +1879,7 @@ writezone(const char *const name, const char *const string, char version) bool dir_checked = false; zic_t one = 1; zic_t y2038_boundary = one << 31; - int nats = timecnt + WORK_AROUND_QTBUG_53071; + ptrdiff_t nats = timecnt + WORK_AROUND_QTBUG_53071; zic_t *ats = emalloc(size_product(nats, sizeof *ats + 1)); void *typesptr = ats + nats; unsigned char *types = typesptr; @@ -1861,8 +1894,8 @@ writezone(const char *const name, const char *const string, char version) * Optimize. */ { - int fromi; - int toi; + ptrdiff_t fromi, + toi; toi = 0; fromi = 0; @@ -1886,9 +1919,17 @@ writezone(const char *const name, const char *const string, char version) } timecnt = toi; } + if (noise && timecnt > 1200) - warning(_("pre-2014 clients may mishandle" - " more than 1200 transition times")); + { + if (timecnt > TZ_MAX_TIMES) + warning(_("reference clients mishandle" + " more than %d transition times"), + TZ_MAX_TIMES); + else + warning(_("pre-2014 clients may mishandle" + " more than 1200 transition times")); + } /* * Transfer. @@ -1991,23 +2032,25 @@ writezone(const char *const name, const char *const string, char version) } for (pass = 1; pass <= 2; ++pass) { - int thistimei, - thistimecnt; + ptrdiff_t thistimei, + thistimecnt, + thistimelim; int thisleapi, - thisleapcnt; - int thistimelim, + thisleapcnt, thisleaplim; int writetype[TZ_MAX_TYPES]; int typemap[TZ_MAX_TYPES]; int thistypecnt; char thischars[TZ_MAX_CHARS]; - char thischarcnt; + int thischarcnt; + bool toomanytimes; int indmap[TZ_MAX_CHARS]; if (pass == 1) { thistimei = timei32; thistimecnt = timecnt32; + toomanytimes = thistimecnt >> 31 >> 1 != 0; thisleapi = leapi32; thisleapcnt = leapcnt32; } @@ -2015,9 +2058,12 @@ writezone(const char *const name, const char *const string, char version) { thistimei = 0; thistimecnt = timecnt; + toomanytimes = thistimecnt >> 31 >> 31 >> 2 != 0; thisleapi = 0; thisleapcnt = leapcnt; } + if (toomanytimes) + error(_("too many transition times")); thistimelim = thistimei + thistimecnt; thisleaplim = thisleapi + thisleapcnt; for (i = 0; i < typecnt; ++i) @@ -2118,8 +2164,7 @@ writezone(const char *const name, const char *const string, char version) break; if (j == thischarcnt) { - strcpy(&thischars[(int) thischarcnt], - thisabbr); + strcpy(&thischars[thischarcnt], thisabbr); thischarcnt += strlen(thisabbr) + 1; } indmap[abbrinds[i]] = j; @@ -2466,13 +2511,13 @@ enum YEAR_BY_YEAR_ZONE = 1}; static int -stringzone(char *result, const struct zone * const zpfirst, const int zonecount) +stringzone(char *result, struct zone const * zpfirst, ptrdiff_t zonecount) { const struct zone *zp; struct rule *rp; struct rule *stdrp; struct rule *dstrp; - int i; + ptrdiff_t i; const char *abbrvar; int compat = 0; int c; @@ -2601,11 +2646,11 @@ stringzone(char *result, const struct zone * const zpfirst, const int zonecount) } static void -outzone(const struct zone * zpfirst, int zonecount) +outzone(const struct zone * zpfirst, ptrdiff_t zonecount) { const struct zone *zp; struct rule *rp; - int i, + ptrdiff_t i, j; bool usestart, useuntil; @@ -2627,7 +2672,7 @@ outzone(const struct zone * zpfirst, int zonecount) int compat; bool do_extend; char version; - int lastatmax = -1; + ptrdiff_t lastatmax = -1; max_abbr_len = 2 + max_format_len + max_abbrvar_len; max_envvar_len = 2 * max_abbr_len + 5 * 9; @@ -2796,7 +2841,7 @@ outzone(const struct zone * zpfirst, int zonecount) } for (;;) { - int k; + ptrdiff_t k; zic_t jtime, ktime = 0; zic_t offset; @@ -3091,30 +3136,52 @@ adjleap(void) } } +static char * +shellquote(char *b, char const * s) +{ + *b++ = '\''; + while (*s) + { + if (*s == '\'') + *b++ = '\'', *b++ = '\\', *b++ = '\''; + *b++ = *s++; + } + *b++ = '\''; + return b; +} + static bool -yearistype(int year, const char *type) +yearistype(zic_t year, const char *type) { - static char *buf; + char *buf; + char *b; int result; if (type == NULL || *type == '\0') return true; - buf = erealloc(buf, 132 + strlen(yitcommand) + strlen(type)); - sprintf(buf, "%s %d %s", yitcommand, year, type); + buf = emalloc(1 + 4 * strlen(yitcommand) + 2 + + INT_STRLEN_MAXIMUM(zic_t) +2 + 4 * strlen(type) + 2); + b = shellquote(buf, yitcommand); + *b++ = ' '; + b += sprintf(b, INT64_FORMAT, year); + *b++ = ' '; + b = shellquote(b, type); + *b = '\0'; result = system(buf); if (WIFEXITED(result)) - switch (WEXITSTATUS(result)) + { + int status = WEXITSTATUS(result); + + if (status <= 1) { - case 0: - return true; - case 1: - return false; + free(buf); + return status == 0; } + } error(_("Wild result from command execution")); fprintf(stderr, _("%s: command was '%s', result was %d\n"), progname, buf, result); - for (;;) - exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } /* Is A a space character in the C locale? */ @@ -3348,7 +3415,7 @@ getfields(char *cp) else { error(_("Odd number of quotation marks")); - exit(1); + exit(EXIT_FAILURE); } } while (*cp && *cp != '#' && !is_space(*cp)); if (is_space(*cp)) @@ -3537,7 +3604,8 @@ newabbr(const char *string) /* Ensure that the directories of ARGNAME exist, by making any missing ones. If ANCESTORS, do this only for ARGNAME's ancestors; otherwise, - do it for ARGNAME too. Exit with failure if there is trouble. */ + do it for ARGNAME too. Exit with failure if there is trouble. + Do not consider an existing non-directory to be trouble. */ static void mkdirs(char const * argname, bool ancestors) { @@ -3569,7 +3637,7 @@ mkdirs(char const * argname, bool ancestors) { int err = errno; - if (err != EEXIST && itsdir(name) < 0) + if (err != EEXIST && !itsdir(name)) { error(_("%s: Cannot create directory %s: %s"), progname, name, strerror(err)); -- cgit v1.2.3 From 32416b0f9a8502e7dff8afbf78e494c091b045e8 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 6 Nov 2016 10:45:58 -0500 Subject: More zic cleanup. The workaround the IANA guys chose to get rid of the clang warning we'd silenced in commit 23ed2ba81 turns out not to satisfy Coverity. Go back to the previous solution, ie, remove the useless comparison to SIZE_MAX. (In principle, there could be machines out there where it's not useless because ptrdiff_t is wider than size_t. But the whole thing is pretty academic anyway, as we could never approach this limit for any sane estimate of the amount of data that zic will ever be asked to work with.) Also, s/lineno/lineno_t/g, because if we accept their decision to start using "lineno" as a typedef, it is going to have very unpleasant consequences in our next pgindent run. Noted that while fooling with pltcl yesterday. --- src/timezone/zic.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'src/timezone/zic.c') diff --git a/src/timezone/zic.c b/src/timezone/zic.c index 7da95aad53..2f623e03a5 100644 --- a/src/timezone/zic.c +++ b/src/timezone/zic.c @@ -48,13 +48,13 @@ static ptrdiff_t const PTRDIFF_MAX = MAXVAL(ptrdiff_t, TYPE_BIT(ptrdiff_t)); #endif /* The type and printf format for line numbers. */ -typedef int lineno; +typedef int lineno_t; #define PRIdLINENO "d" struct rule { const char *r_filename; - lineno r_linenum; + lineno_t r_linenum; const char *r_name; zic_t r_loyear; /* for example, 1986 */ @@ -91,7 +91,7 @@ struct rule struct zone { const char *z_filename; - lineno z_linenum; + lineno_t z_linenum; const char *z_name; zic_t z_gmtoff; @@ -169,7 +169,7 @@ static int leapcnt; static bool leapseen; static zic_t leapminyear; static zic_t leapmaxyear; -static lineno linenum; +static lineno_t linenum; static int max_abbrvar_len = PERCENT_Z_LEN_BOUND; static int max_format_len; static zic_t max_year; @@ -178,7 +178,7 @@ static bool noise; static bool print_abbrevs; static zic_t print_cutoff; static const char *rfilename; -static lineno rlinenum; +static lineno_t rlinenum; static const char *progname; static ptrdiff_t timecnt; static ptrdiff_t timecnt_alloc; @@ -276,7 +276,7 @@ static ptrdiff_t nzones_alloc; struct link { const char *l_filename; - lineno l_linenum; + lineno_t l_linenum; const char *l_from; const char *l_to; }; @@ -430,14 +430,13 @@ ecpyalloc(char const * str) } static void * -growalloc(void *ptr, size_t itemsize, ptrdiff_t nitems, ptrdiff_t * nitems_alloc) +growalloc(void *ptr, size_t itemsize, ptrdiff_t nitems, ptrdiff_t *nitems_alloc) { if (nitems < *nitems_alloc) return ptr; else { - ptrdiff_t nitems_max = PTRDIFF_MAX - WORK_AROUND_QTBUG_53071; - ptrdiff_t amax = nitems_max < SIZE_MAX ? nitems_max : SIZE_MAX; + ptrdiff_t amax = PTRDIFF_MAX - WORK_AROUND_QTBUG_53071; if ((amax - 1) / 3 * 2 < *nitems_alloc) memory_exhausted(_("integer overflow")); @@ -451,7 +450,7 @@ growalloc(void *ptr, size_t itemsize, ptrdiff_t nitems, ptrdiff_t * nitems_alloc */ static void -eats(char const * name, lineno num, char const * rname, lineno rnum) +eats(char const * name, lineno_t num, char const * rname, lineno_t rnum) { filename = name; linenum = num; @@ -460,7 +459,7 @@ eats(char const * name, lineno num, char const * rname, lineno rnum) } static void -eat(char const * name, lineno num) +eat(char const * name, lineno_t num) { eats(name, num, NULL, -1); } @@ -1157,7 +1156,7 @@ infile(const char *name) const struct lookup *lp; int nfields; bool wantcont; - lineno num; + lineno_t num; char buf[BUFSIZ]; if (strcmp(name, "-") == 0) -- cgit v1.2.3 From 93513d1b6559b2d0805f0b02d312ee550e3d010b Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 15 Dec 2016 14:32:42 -0500 Subject: Sync our copy of the timezone library with IANA release tzcode2016j. This is a trivial update (consisting in fact only in the addition of a comment). The point is just to get back to being synced with an official release of tzcode, rather than some ad-hoc point in their commit history, which is where commit 1f87181e1 left it. --- src/timezone/README | 2 +- src/timezone/zic.c | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'src/timezone/zic.c') diff --git a/src/timezone/README b/src/timezone/README index f2f80c7176..a82d77c7ba 100644 --- a/src/timezone/README +++ b/src/timezone/README @@ -50,7 +50,7 @@ match properly on the old version. Time Zone code ============== -The code in this directory is currently synced with tzcode release 2016c. +The code in this directory is currently synced with tzcode release 2016j. There are many cosmetic (and not so cosmetic) differences from the original tzcode library, but diffs in the upstream version should usually be propagated to our version. Here are some notes about that. diff --git a/src/timezone/zic.c b/src/timezone/zic.c index 2f623e03a5..a83cea12dd 100644 --- a/src/timezone/zic.c +++ b/src/timezone/zic.c @@ -3634,6 +3634,11 @@ mkdirs(char const * argname, bool ancestors) */ if (mkdir(name, MKDIR_UMASK) != 0) { + /* + * For speed, skip itsdir if errno == EEXIST. Since mkdirs is + * called only after open fails with ENOENT on a subfile, EEXIST + * implies itsdir here. + */ int err = errno; if (err != EEXIST && !itsdir(name)) -- cgit v1.2.3 From 9e3755ecb2d058f7d123dd35a2e1784006190962 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sat, 25 Feb 2017 16:12:24 -0500 Subject: Remove useless duplicate inclusions of system header files. c.h #includes a number of core libc header files, such as . There's no point in re-including these after having read postgres.h, postgres_fe.h, or c.h; so remove code that did so. While at it, also fix some places that were ignoring our standard pattern of "include postgres[_fe].h, then system header files, then other Postgres header files". While there's not any great magic in doing it that way rather than system headers last, it's silly to have just a few files deviating from the general pattern. (But I didn't attempt to enforce this globally, only in files I was touching anyway.) I'd be the first to say that this is mostly compulsive neatnik-ism, but over time it might save enough compile cycles to be useful. --- contrib/fuzzystrmatch/dmetaphone.c | 12 +++++++----- contrib/ltree/crc32.c | 4 ---- contrib/pgcrypto/px.h | 1 - src/backend/access/transam/timeline.c | 1 - src/backend/access/transam/twophase.c | 1 - src/backend/access/transam/xlogarchive.c | 1 - src/backend/commands/dbcommands.c | 1 - src/backend/commands/tablespace.c | 1 - src/backend/libpq/ifaddr.c | 1 - src/backend/port/atomics.c | 1 - src/backend/port/dynloader/freebsd.h | 1 - src/backend/port/dynloader/netbsd.h | 1 - src/backend/port/dynloader/openbsd.h | 1 - src/backend/port/win32/crashdump.c | 3 +-- src/backend/postmaster/autovacuum.c | 1 - src/backend/replication/basebackup.c | 1 - src/backend/replication/logical/snapbuild.c | 1 - src/backend/replication/walreceiverfuncs.c | 1 - src/backend/storage/ipc/dsm.c | 1 - src/backend/storage/ipc/dsm_impl.c | 1 - src/backend/storage/ipc/latch.c | 1 - src/backend/utils/adt/cash.c | 1 - src/backend/utils/adt/dbsize.c | 1 - src/backend/utils/adt/inet_cidr_ntop.c | 1 - src/backend/utils/adt/inet_net_pton.c | 1 - src/backend/utils/adt/pg_locale.c | 1 - src/backend/utils/init/miscinit.c | 1 - src/bin/initdb/initdb.c | 1 - src/bin/pg_basebackup/pg_basebackup.c | 1 - src/bin/pg_basebackup/pg_receivewal.c | 1 - src/bin/pg_basebackup/streamutil.c | 3 --- src/bin/pg_ctl/pg_ctl.c | 11 ++++------- src/bin/pg_dump/parallel.c | 14 ++++++-------- src/bin/pg_dump/pg_backup_archiver.c | 16 +++++++--------- src/bin/pg_dump/pg_dump.c | 3 --- src/bin/pg_dump/pg_dumpall.c | 4 ---- src/bin/pg_dump/pg_restore.c | 15 +++++---------- src/bin/pg_resetwal/pg_resetwal.c | 1 - src/bin/pg_rewind/copy_fetch.c | 2 -- src/bin/pg_rewind/fetch.c | 1 - src/bin/pg_rewind/file_ops.c | 1 - src/bin/pg_rewind/filemap.c | 1 - src/bin/pg_rewind/libpq_fetch.c | 1 - src/bin/pg_upgrade/dump.c | 1 - src/bin/pg_upgrade/exec.c | 5 ++--- src/bin/pg_upgrade/option.c | 11 +++++------ src/bin/pg_upgrade/parallel.c | 9 +++------ src/bin/pg_upgrade/tablespace.c | 2 -- src/bin/pgevent/pgevent.c | 6 ------ src/bin/psql/command.c | 2 -- src/bin/psql/crosstabview.c | 2 -- src/bin/psql/help.c | 1 - src/bin/psql/startup.c | 4 ---- src/common/ip.c | 1 - src/common/username.c | 2 -- src/common/wait_error.c | 2 -- src/fe_utils/print.c | 1 - src/include/libpq/libpq.h | 1 - src/include/port/atomics/generic-msvc.h | 1 - src/include/utils/pg_locale.h | 1 - src/interfaces/ecpg/ecpglib/data.c | 2 -- src/interfaces/ecpg/ecpglib/execute.c | 1 - src/interfaces/ecpg/ecpglib/typename.c | 1 - src/interfaces/ecpg/preproc/ecpg.c | 2 +- src/interfaces/ecpg/preproc/pgc.l | 1 - src/interfaces/libpq/fe-connect.c | 1 - src/interfaces/libpq/libpq-int.h | 1 - src/interfaces/libpq/pthread-win32.c | 1 - src/pl/plperl/plperl.c | 1 - src/port/chklocale.c | 5 ----- src/port/dirmod.c | 1 - src/port/inet_net_ntop.c | 1 - src/port/open.c | 1 - src/port/system.c | 1 - src/test/isolation/isolationtester.c | 3 --- src/timezone/strftime.c | 1 - src/timezone/zic.c | 1 - 77 files changed, 41 insertions(+), 155 deletions(-) (limited to 'src/timezone/zic.c') diff --git a/contrib/fuzzystrmatch/dmetaphone.c b/contrib/fuzzystrmatch/dmetaphone.c index 147c8501ee..f210869acb 100644 --- a/contrib/fuzzystrmatch/dmetaphone.c +++ b/contrib/fuzzystrmatch/dmetaphone.c @@ -93,9 +93,6 @@ The remaining code is authored by Andrew Dunstan and ***********************************************************************/ - - - /* include these first, according to the docs */ #ifndef DMETAPHONE_MAIN @@ -105,14 +102,19 @@ The remaining code is authored by Andrew Dunstan and /* turn off assertions for embedded function */ #define NDEBUG -#endif +#else /* DMETAPHONE_MAIN */ + +/* we need these if we didn't get them from postgres.h */ #include -#include #include #include #include + +#endif /* DMETAPHONE_MAIN */ + #include +#include /* prototype for the main function we got from the perl module */ static void DoubleMetaphone(char *, char **); diff --git a/contrib/ltree/crc32.c b/contrib/ltree/crc32.c index 403dae0d7d..447e4b2960 100644 --- a/contrib/ltree/crc32.c +++ b/contrib/ltree/crc32.c @@ -9,10 +9,6 @@ #include "postgres.h" -#include -#include -#include - #ifdef LOWER_NODE #include #define TOLOWER(x) tolower((unsigned char) (x)) diff --git a/contrib/pgcrypto/px.h b/contrib/pgcrypto/px.h index 00fc6f0c01..e68a95a058 100644 --- a/contrib/pgcrypto/px.h +++ b/contrib/pgcrypto/px.h @@ -32,7 +32,6 @@ #ifndef __PX_H #define __PX_H -#include #include /* keep debug messages? */ diff --git a/src/backend/access/transam/timeline.c b/src/backend/access/transam/timeline.c index c8240b112d..1fdc59190c 100644 --- a/src/backend/access/transam/timeline.c +++ b/src/backend/access/transam/timeline.c @@ -32,7 +32,6 @@ #include "postgres.h" #include -#include #include #include "access/timeline.h" diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 50c70b2920..0a8edb9e58 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -54,7 +54,6 @@ #include #include -#include #include #include diff --git a/src/backend/access/transam/xlogarchive.c b/src/backend/access/transam/xlogarchive.c index 7e91e8f81a..7afb73579b 100644 --- a/src/backend/access/transam/xlogarchive.c +++ b/src/backend/access/transam/xlogarchive.c @@ -14,7 +14,6 @@ #include "postgres.h" -#include #include #include #include diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index 1ebacbc24f..5a63b1abcb 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -20,7 +20,6 @@ #include "postgres.h" #include -#include #include #include diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c index 80515bae19..f9c26201d9 100644 --- a/src/backend/commands/tablespace.c +++ b/src/backend/commands/tablespace.c @@ -48,7 +48,6 @@ #include #include -#include #include #include "access/heapam.h" diff --git a/src/backend/libpq/ifaddr.c b/src/backend/libpq/ifaddr.c index 7692881c8b..f81003f7c8 100644 --- a/src/backend/libpq/ifaddr.c +++ b/src/backend/libpq/ifaddr.c @@ -20,7 +20,6 @@ #include "postgres.h" #include -#include #include #include #include diff --git a/src/backend/port/atomics.c b/src/backend/port/atomics.c index 86b5308214..756a2ef997 100644 --- a/src/backend/port/atomics.c +++ b/src/backend/port/atomics.c @@ -21,7 +21,6 @@ #ifdef WIN32 #error "barriers are required (and provided) on WIN32 platforms" #endif -#include #include #endif diff --git a/src/backend/port/dynloader/freebsd.h b/src/backend/port/dynloader/freebsd.h index 78dda69922..6116d3f83f 100644 --- a/src/backend/port/dynloader/freebsd.h +++ b/src/backend/port/dynloader/freebsd.h @@ -13,7 +13,6 @@ #ifndef PORT_PROTOS_H #define PORT_PROTOS_H -#include #include #include #include diff --git a/src/backend/port/dynloader/netbsd.h b/src/backend/port/dynloader/netbsd.h index 688b7fb793..0bd406850d 100644 --- a/src/backend/port/dynloader/netbsd.h +++ b/src/backend/port/dynloader/netbsd.h @@ -14,7 +14,6 @@ #ifndef PORT_PROTOS_H #define PORT_PROTOS_H -#include #include #include #include diff --git a/src/backend/port/dynloader/openbsd.h b/src/backend/port/dynloader/openbsd.h index 34d2724615..25d5439633 100644 --- a/src/backend/port/dynloader/openbsd.h +++ b/src/backend/port/dynloader/openbsd.h @@ -13,7 +13,6 @@ #ifndef PORT_PROTOS_H #define PORT_PROTOS_H -#include #include #include #include diff --git a/src/backend/port/win32/crashdump.c b/src/backend/port/win32/crashdump.c index 64969df73d..ff44b6033e 100644 --- a/src/backend/port/win32/crashdump.c +++ b/src/backend/port/win32/crashdump.c @@ -39,8 +39,7 @@ #include "postgres.h" #define WIN32_LEAN_AND_MEAN -#include -#include + /* * Some versions of the MS SDK contain "typedef enum { ... } ;" which the MS * compiler quite sanely complains about. Well done, Microsoft. diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 0c5ffa086c..e8de9a3ced 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -62,7 +62,6 @@ #include "postgres.h" #include -#include #include #include diff --git a/src/backend/replication/basebackup.c b/src/backend/replication/basebackup.c index 643a17943a..7414048f4e 100644 --- a/src/backend/replication/basebackup.c +++ b/src/backend/replication/basebackup.c @@ -12,7 +12,6 @@ */ #include "postgres.h" -#include #include #include #include diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c0f28ddc09..6f19cdca8c 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -107,7 +107,6 @@ #include "postgres.h" #include -#include #include #include "miscadmin.h" diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c index df113b86e8..8bf1fe8565 100644 --- a/src/backend/replication/walreceiverfuncs.c +++ b/src/backend/replication/walreceiverfuncs.c @@ -16,7 +16,6 @@ */ #include "postgres.h" -#include #include #include #include diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index 07af16622c..54378bcea9 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -27,7 +27,6 @@ #include "postgres.h" #include -#include #include #ifndef WIN32 #include diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c index 7078f68c35..b2c9cdc6ed 100644 --- a/src/backend/storage/ipc/dsm_impl.c +++ b/src/backend/storage/ipc/dsm_impl.c @@ -49,7 +49,6 @@ #include "postgres.h" #include -#include #include #ifndef WIN32 #include diff --git a/src/backend/storage/ipc/latch.c b/src/backend/storage/ipc/latch.c index 0079ba567f..ea7f930866 100644 --- a/src/backend/storage/ipc/latch.c +++ b/src/backend/storage/ipc/latch.c @@ -40,7 +40,6 @@ #include #include #include -#include #ifdef HAVE_SYS_EPOLL_H #include #endif diff --git a/src/backend/utils/adt/cash.c b/src/backend/utils/adt/cash.c index ac8f74fee6..5afadb65d1 100644 --- a/src/backend/utils/adt/cash.c +++ b/src/backend/utils/adt/cash.c @@ -21,7 +21,6 @@ #include #include #include -#include #include "libpq/pqformat.h" #include "utils/builtins.h" diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c index ec3a28cd0d..8cdd1dc4f7 100644 --- a/src/backend/utils/adt/dbsize.c +++ b/src/backend/utils/adt/dbsize.c @@ -11,7 +11,6 @@ #include "postgres.h" -#include #include #include "access/heapam.h" diff --git a/src/backend/utils/adt/inet_cidr_ntop.c b/src/backend/utils/adt/inet_cidr_ntop.c index d33534ec17..d5d1289d7d 100644 --- a/src/backend/utils/adt/inet_cidr_ntop.c +++ b/src/backend/utils/adt/inet_cidr_ntop.c @@ -23,7 +23,6 @@ static const char rcsid[] = "Id: inet_net_ntop.c,v 1.1.2.2 2004/03/09 09:17:27 m #include "postgres.h" -#include #include #include #include diff --git a/src/backend/utils/adt/inet_net_pton.c b/src/backend/utils/adt/inet_net_pton.c index b8fa7d2bcc..be788d37cd 100644 --- a/src/backend/utils/adt/inet_net_pton.c +++ b/src/backend/utils/adt/inet_net_pton.c @@ -23,7 +23,6 @@ static const char rcsid[] = "Id: inet_net_pton.c,v 1.4.2.3 2004/03/17 00:40:11 m #include "postgres.h" -#include #include #include #include diff --git a/src/backend/utils/adt/pg_locale.c b/src/backend/utils/adt/pg_locale.c index 4c7f1dad50..ab197025f8 100644 --- a/src/backend/utils/adt/pg_locale.c +++ b/src/backend/utils/adt/pg_locale.c @@ -51,7 +51,6 @@ #include "postgres.h" -#include #include #include "access/htup_details.h" diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c index e984e79c60..e0298ee35f 100644 --- a/src/backend/utils/init/miscinit.c +++ b/src/backend/utils/init/miscinit.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index 540427a892..1ed0d20504 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -52,7 +52,6 @@ #include #include #include -#include #include #include diff --git a/src/bin/pg_basebackup/pg_basebackup.c b/src/bin/pg_basebackup/pg_basebackup.c index 9020fb14d3..bc997dc997 100644 --- a/src/bin/pg_basebackup/pg_basebackup.c +++ b/src/bin/pg_basebackup/pg_basebackup.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include diff --git a/src/bin/pg_basebackup/pg_receivewal.c b/src/bin/pg_basebackup/pg_receivewal.c index e8d0e8984e..15348ada58 100644 --- a/src/bin/pg_basebackup/pg_receivewal.c +++ b/src/bin/pg_basebackup/pg_receivewal.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include "libpq-fe.h" diff --git a/src/bin/pg_basebackup/streamutil.c b/src/bin/pg_basebackup/streamutil.c index 90d93cbed1..1fe42efc21 100644 --- a/src/bin/pg_basebackup/streamutil.c +++ b/src/bin/pg_basebackup/streamutil.c @@ -13,10 +13,7 @@ #include "postgres_fe.h" -#include -#include #include -#include #include /* for ntohl/htonl */ diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c index 93e5891950..c63819b88b 100644 --- a/src/bin/pg_ctl/pg_ctl.c +++ b/src/bin/pg_ctl/pg_ctl.c @@ -19,16 +19,9 @@ #include "postgres_fe.h" -#include "catalog/pg_control.h" -#include "common/controldata_utils.h" -#include "libpq-fe.h" -#include "pqexpbuffer.h" - #include -#include #include #include -#include #include #include #include @@ -38,8 +31,12 @@ #include #endif +#include "catalog/pg_control.h" +#include "common/controldata_utils.h" #include "getopt_long.h" +#include "libpq-fe.h" #include "miscadmin.h" +#include "pqexpbuffer.h" /* PID can be negative for standalone backend */ typedef long pgpid_t; diff --git a/src/bin/pg_dump/parallel.c b/src/bin/pg_dump/parallel.c index 775a7f858c..be8e018a96 100644 --- a/src/bin/pg_dump/parallel.c +++ b/src/bin/pg_dump/parallel.c @@ -51,6 +51,12 @@ #include "postgres_fe.h" +#ifndef WIN32 +#include +#include +#include +#include +#endif #ifdef HAVE_SYS_SELECT_H #include #endif @@ -59,14 +65,6 @@ #include "pg_backup_utils.h" #include "fe_utils/string_utils.h" -#ifndef WIN32 -#include -#include -#include "signal.h" -#include -#include -#endif - /* Mnemonic macros for indexing the fd array returned by pipe(2) */ #define PIPE_READ 0 #define PIPE_WRITE 1 diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index 929f1b592b..7e2bed38b3 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -21,24 +21,22 @@ */ #include "postgres_fe.h" -#include "parallel.h" -#include "pg_backup_archiver.h" -#include "pg_backup_db.h" -#include "pg_backup_utils.h" -#include "dumputils.h" -#include "fe_utils/string_utils.h" - #include #include #include #include -#include #include - #ifdef WIN32 #include #endif +#include "parallel.h" +#include "pg_backup_archiver.h" +#include "pg_backup_db.h" +#include "pg_backup_utils.h" +#include "dumputils.h" +#include "fe_utils/string_utils.h" + #include "libpq/libpq-fs.h" #define TEXT_DUMP_HEADER "--\n-- PostgreSQL database dump\n--\n\n" diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 89db3103bc..7273ec8fe2 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -33,9 +33,6 @@ #include #include -#ifdef ENABLE_NLS -#include -#endif #ifdef HAVE_TERMIOS_H #include #endif diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c index 6895d02bfc..f4b4d7bd9b 100644 --- a/src/bin/pg_dump/pg_dumpall.c +++ b/src/bin/pg_dump/pg_dumpall.c @@ -18,10 +18,6 @@ #include #include -#ifdef ENABLE_NLS -#include -#endif - #include "getopt_long.h" #include "dumputils.h" diff --git a/src/bin/pg_dump/pg_restore.c b/src/bin/pg_dump/pg_restore.c index 497677494b..5f61fb2764 100644 --- a/src/bin/pg_dump/pg_restore.c +++ b/src/bin/pg_dump/pg_restore.c @@ -40,21 +40,16 @@ */ #include "postgres_fe.h" -#include "getopt_long.h" - -#include "dumputils.h" -#include "parallel.h" -#include "pg_backup_utils.h" - #include - #ifdef HAVE_TERMIOS_H #include #endif -#ifdef ENABLE_NLS -#include -#endif +#include "getopt_long.h" + +#include "dumputils.h" +#include "parallel.h" +#include "pg_backup_utils.h" static void usage(const char *progname); diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c index 502ea5b290..27bd9b04e7 100644 --- a/src/bin/pg_resetwal/pg_resetwal.c +++ b/src/bin/pg_resetwal/pg_resetwal.c @@ -39,7 +39,6 @@ #include #include -#include #include #include #include diff --git a/src/bin/pg_rewind/copy_fetch.c b/src/bin/pg_rewind/copy_fetch.c index d48424bfb4..f8d3dfecfa 100644 --- a/src/bin/pg_rewind/copy_fetch.c +++ b/src/bin/pg_rewind/copy_fetch.c @@ -9,12 +9,10 @@ */ #include "postgres_fe.h" -#include #include #include #include #include -#include #include "datapagemap.h" #include "fetch.h" diff --git a/src/bin/pg_rewind/fetch.c b/src/bin/pg_rewind/fetch.c index 08a296d7d4..e9353d8866 100644 --- a/src/bin/pg_rewind/fetch.c +++ b/src/bin/pg_rewind/fetch.c @@ -16,7 +16,6 @@ */ #include "postgres_fe.h" -#include #include #include diff --git a/src/bin/pg_rewind/file_ops.c b/src/bin/pg_rewind/file_ops.c index f8ca4c925d..4229f0e056 100644 --- a/src/bin/pg_rewind/file_ops.c +++ b/src/bin/pg_rewind/file_ops.c @@ -14,7 +14,6 @@ */ #include "postgres_fe.h" -#include #include #include #include diff --git a/src/bin/pg_rewind/filemap.c b/src/bin/pg_rewind/filemap.c index 151930234c..e5b254069d 100644 --- a/src/bin/pg_rewind/filemap.c +++ b/src/bin/pg_rewind/filemap.c @@ -10,7 +10,6 @@ #include "postgres_fe.h" -#include #include #include diff --git a/src/bin/pg_rewind/libpq_fetch.c b/src/bin/pg_rewind/libpq_fetch.c index d2374201c6..d86ecd3660 100644 --- a/src/bin/pg_rewind/libpq_fetch.c +++ b/src/bin/pg_rewind/libpq_fetch.c @@ -9,7 +9,6 @@ */ #include "postgres_fe.h" -#include #include #include #include diff --git a/src/bin/pg_upgrade/dump.c b/src/bin/pg_upgrade/dump.c index f18be22c16..2e621b027c 100644 --- a/src/bin/pg_upgrade/dump.c +++ b/src/bin/pg_upgrade/dump.c @@ -11,7 +11,6 @@ #include "pg_upgrade.h" -#include #include "fe_utils/string_utils.h" diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index b6a3ef791e..91fa71728e 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -9,10 +9,9 @@ #include "postgres_fe.h" -#include "pg_upgrade.h" - #include -#include + +#include "pg_upgrade.h" static void check_data_dir(ClusterInfo *cluster); static void check_bin_dir(ClusterInfo *cluster); diff --git a/src/bin/pg_upgrade/option.c b/src/bin/pg_upgrade/option.c index 82d2443bcd..5007ce53cf 100644 --- a/src/bin/pg_upgrade/option.c +++ b/src/bin/pg_upgrade/option.c @@ -9,17 +9,16 @@ #include "postgres_fe.h" -#include "miscadmin.h" -#include "getopt_long.h" - -#include "pg_upgrade.h" - #include -#include #ifdef WIN32 #include #endif +#include "miscadmin.h" +#include "getopt_long.h" + +#include "pg_upgrade.h" + static void usage(void); static void check_required_directory(char **dirpath, char **configpath, diff --git a/src/bin/pg_upgrade/parallel.c b/src/bin/pg_upgrade/parallel.c index d35015f52a..7c85a13a99 100644 --- a/src/bin/pg_upgrade/parallel.c +++ b/src/bin/pg_upgrade/parallel.c @@ -9,17 +9,14 @@ #include "postgres_fe.h" -#include "pg_upgrade.h" - -#include -#include -#include #include - #ifdef WIN32 #include #endif +#include "pg_upgrade.h" + + static int parallel_jobs; #ifdef WIN32 diff --git a/src/bin/pg_upgrade/tablespace.c b/src/bin/pg_upgrade/tablespace.c index 24f7bd960c..4938bc2de2 100644 --- a/src/bin/pg_upgrade/tablespace.c +++ b/src/bin/pg_upgrade/tablespace.c @@ -11,8 +11,6 @@ #include "pg_upgrade.h" -#include - static void get_tablespace_paths(void); static void set_tablespace_directory_suffix(ClusterInfo *cluster); diff --git a/src/bin/pgevent/pgevent.c b/src/bin/pgevent/pgevent.c index 5332a13256..f68f987c17 100644 --- a/src/bin/pgevent/pgevent.c +++ b/src/bin/pgevent/pgevent.c @@ -10,15 +10,9 @@ * *------------------------------------------------------------------------- */ - - #include "postgres_fe.h" -#include #include -#include -#include -#include /* Global variables */ HANDLE g_module = NULL; /* hModule of DLL */ diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index f17f610717..a28f5134b9 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -18,7 +18,6 @@ #include #endif #ifndef WIN32 -#include /* for umask() */ #include /* for stat() */ #include /* open() flags */ #include /* for geteuid(), getpid(), stat() */ @@ -27,7 +26,6 @@ #include #include #include -#include /* for umask() */ #include /* for stat() */ #endif diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index bf48d2f406..2794eb6b87 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -7,8 +7,6 @@ */ #include "postgres_fe.h" -#include - #include "common.h" #include "crosstabview.h" #include "pqexpbuffer.h" diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c index 3e3cab4941..91cf0be46a 100644 --- a/src/bin/psql/help.c +++ b/src/bin/psql/help.c @@ -8,7 +8,6 @@ #include "postgres_fe.h" #ifndef WIN32 -#include /* (ditto) */ #include /* for geteuid() */ #else #include diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c index 88d686a5b7..694f0ef257 100644 --- a/src/bin/psql/startup.c +++ b/src/bin/psql/startup.c @@ -7,8 +7,6 @@ */ #include "postgres_fe.h" -#include - #ifndef WIN32 #include #else /* WIN32 */ @@ -18,8 +16,6 @@ #include "getopt_long.h" -#include - #include "command.h" #include "common.h" #include "describe.h" diff --git a/src/common/ip.c b/src/common/ip.c index d981dbcac9..80711dbb98 100644 --- a/src/common/ip.c +++ b/src/common/ip.c @@ -24,7 +24,6 @@ #endif #include -#include #include #include #include diff --git a/src/common/username.c b/src/common/username.c index d6abac8281..487eacfe73 100644 --- a/src/common/username.c +++ b/src/common/username.c @@ -18,10 +18,8 @@ #include "postgres_fe.h" #endif -#include #include #include -#include #include "common/username.h" diff --git a/src/common/wait_error.c b/src/common/wait_error.c index 7ac545c67a..f824a5f2af 100644 --- a/src/common/wait_error.c +++ b/src/common/wait_error.c @@ -21,8 +21,6 @@ #endif #include -#include -#include #include /* diff --git a/src/fe_utils/print.c b/src/fe_utils/print.c index 5ca27a93e0..9180b90004 100644 --- a/src/fe_utils/print.c +++ b/src/fe_utils/print.c @@ -18,7 +18,6 @@ #include "postgres_fe.h" #include -#include #include #include #include diff --git a/src/include/libpq/libpq.h b/src/include/libpq/libpq.h index 538066e106..d4885a5e28 100644 --- a/src/include/libpq/libpq.h +++ b/src/include/libpq/libpq.h @@ -14,7 +14,6 @@ #ifndef LIBPQ_H #define LIBPQ_H -#include #include #include "lib/stringinfo.h" diff --git a/src/include/port/atomics/generic-msvc.h b/src/include/port/atomics/generic-msvc.h index c7caf04d57..d5ee6e1bcb 100644 --- a/src/include/port/atomics/generic-msvc.h +++ b/src/include/port/atomics/generic-msvc.h @@ -17,7 +17,6 @@ *------------------------------------------------------------------------- */ #include -#include /* intentionally no include guards, should only be included by atomics.h */ #ifndef INSIDE_ATOMICS_H diff --git a/src/include/utils/pg_locale.h b/src/include/utils/pg_locale.h index be91f9b88c..cb509e2b6b 100644 --- a/src/include/utils/pg_locale.h +++ b/src/include/utils/pg_locale.h @@ -12,7 +12,6 @@ #ifndef _PG_LOCALE_ #define _PG_LOCALE_ -#include #if defined(LOCALE_T_IN_XLOCALE) || defined(WCSTOMBS_L_IN_XLOCALE) #include #endif diff --git a/src/interfaces/ecpg/ecpglib/data.c b/src/interfaces/ecpg/ecpglib/data.c index 23646a9579..499a4c1780 100644 --- a/src/interfaces/ecpg/ecpglib/data.c +++ b/src/interfaces/ecpg/ecpglib/data.c @@ -3,8 +3,6 @@ #define POSTGRES_ECPG_INTERNAL #include "postgres_fe.h" -#include -#include #include #include diff --git a/src/interfaces/ecpg/ecpglib/execute.c b/src/interfaces/ecpg/ecpglib/execute.c index d5a463d940..bd9b86be49 100644 --- a/src/interfaces/ecpg/ecpglib/execute.c +++ b/src/interfaces/ecpg/ecpglib/execute.c @@ -16,7 +16,6 @@ #define POSTGRES_ECPG_INTERNAL #include "postgres_fe.h" -#include #include #include diff --git a/src/interfaces/ecpg/ecpglib/typename.c b/src/interfaces/ecpg/ecpglib/typename.c index db65ec10f1..f90279cf81 100644 --- a/src/interfaces/ecpg/ecpglib/typename.c +++ b/src/interfaces/ecpg/ecpglib/typename.c @@ -3,7 +3,6 @@ #define POSTGRES_ECPG_INTERNAL #include "postgres_fe.h" -#include #include "ecpgtype.h" #include "ecpglib.h" #include "extern.h" diff --git a/src/interfaces/ecpg/preproc/ecpg.c b/src/interfaces/ecpg/preproc/ecpg.c index fa80bb289e..aaecbf8122 100644 --- a/src/interfaces/ecpg/preproc/ecpg.c +++ b/src/interfaces/ecpg/preproc/ecpg.c @@ -6,7 +6,7 @@ #include "postgres_fe.h" #include -#include + #include "getopt_long.h" #include "extern.h" diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l index b894a33e53..6b58dd5afe 100644 --- a/src/interfaces/ecpg/preproc/pgc.l +++ b/src/interfaces/ecpg/preproc/pgc.l @@ -19,7 +19,6 @@ #include "postgres_fe.h" #include -#include #include #include "extern.h" diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 65b7c31dc0..685f355ab3 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -15,7 +15,6 @@ #include "postgres_fe.h" -#include #include #include #include diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h index e9b73a925e..24242da221 100644 --- a/src/interfaces/libpq/libpq-int.h +++ b/src/interfaces/libpq/libpq-int.h @@ -25,7 +25,6 @@ #include "libpq-events.h" #include -#include #ifndef WIN32 #include #endif diff --git a/src/interfaces/libpq/pthread-win32.c b/src/interfaces/libpq/pthread-win32.c index e63432d822..0e0d3eeb88 100644 --- a/src/interfaces/libpq/pthread-win32.c +++ b/src/interfaces/libpq/pthread-win32.c @@ -12,7 +12,6 @@ #include "postgres_fe.h" -#include #include "pthread-win32.h" DWORD diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c index fc10d30f45..00979cba74 100644 --- a/src/pl/plperl/plperl.c +++ b/src/pl/plperl/plperl.c @@ -13,7 +13,6 @@ #include #include #include -#include #include /* postgreSQL stuff */ diff --git a/src/port/chklocale.c b/src/port/chklocale.c index 54ce9410f0..c6ec929702 100644 --- a/src/port/chklocale.c +++ b/src/port/chklocale.c @@ -19,11 +19,6 @@ #include "postgres_fe.h" #endif -#if defined(WIN32) && (_MSC_VER >= 1900) -#include -#endif - -#include #ifdef HAVE_LANGINFO_H #include #endif diff --git a/src/port/dirmod.c b/src/port/dirmod.c index 08835962be..84039ff38a 100644 --- a/src/port/dirmod.c +++ b/src/port/dirmod.c @@ -34,7 +34,6 @@ #ifndef __CYGWIN__ #include #else -#include #include #endif #endif diff --git a/src/port/inet_net_ntop.c b/src/port/inet_net_ntop.c index 047895e4f4..cebcda0e61 100644 --- a/src/port/inet_net_ntop.c +++ b/src/port/inet_net_ntop.c @@ -27,7 +27,6 @@ static const char rcsid[] = "Id: inet_net_ntop.c,v 1.1.2.2 2004/03/09 09:17:27 m #include "postgres_fe.h" #endif -#include #include #include #include diff --git a/src/port/open.c b/src/port/open.c index db7abdbe03..aa31342261 100644 --- a/src/port/open.c +++ b/src/port/open.c @@ -19,7 +19,6 @@ #include "postgres_fe.h" #endif -#include #include #include diff --git a/src/port/system.c b/src/port/system.c index 8651187890..3d99c7985f 100644 --- a/src/port/system.c +++ b/src/port/system.c @@ -44,7 +44,6 @@ #include "postgres_fe.h" #endif -#include #include #undef system diff --git a/src/test/isolation/isolationtester.c b/src/test/isolation/isolationtester.c index db2b55982b..f77f465751 100644 --- a/src/test/isolation/isolationtester.c +++ b/src/test/isolation/isolationtester.c @@ -7,9 +7,6 @@ #include "postgres_fe.h" -#ifdef WIN32 -#include -#endif #include #ifdef HAVE_SYS_SELECT_H #include diff --git a/src/timezone/strftime.c b/src/timezone/strftime.c index 4a0a01db65..acaba86881 100644 --- a/src/timezone/strftime.c +++ b/src/timezone/strftime.c @@ -41,7 +41,6 @@ #include "postgres.h" #include -#include #include "private.h" #include "tzfile.h" diff --git a/src/timezone/zic.c b/src/timezone/zic.c index a83cea12dd..e1875585df 100644 --- a/src/timezone/zic.c +++ b/src/timezone/zic.c @@ -9,7 +9,6 @@ #include "postgres_fe.h" #include -#include #include #include #include -- cgit v1.2.3 From e18b2c480da478f62781e06488cda56fe1b4e919 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 30 Apr 2017 15:13:51 -0400 Subject: Sync our copy of the timezone library with IANA release tzcode2017b. zic no longer mishandles some transitions in January 2038 when it attempts to work around Qt bug 53071. This fixes a bug affecting Pacific/Tongatapu that was introduced in zic 2016e. localtime.c now contains a workaround, useful when loading a file generated by a buggy zic. There are assorted cosmetic changes as well, notably relocation of a bunch of #defines. --- src/timezone/README | 2 +- src/timezone/localtime.c | 73 +++++++++++++++++++++++++++++++++++----------- src/timezone/pgtz.c | 9 +++--- src/timezone/private.h | 76 ++++++++++++++++++++++++++++++++++++------------ src/timezone/strftime.c | 11 +++++-- src/timezone/tzfile.h | 52 --------------------------------- src/timezone/zic.c | 15 ++++++++-- 7 files changed, 139 insertions(+), 99 deletions(-) (limited to 'src/timezone/zic.c') diff --git a/src/timezone/README b/src/timezone/README index a82d77c7ba..2544230c4c 100644 --- a/src/timezone/README +++ b/src/timezone/README @@ -50,7 +50,7 @@ match properly on the old version. Time Zone code ============== -The code in this directory is currently synced with tzcode release 2016j. +The code in this directory is currently synced with tzcode release 2017b. There are many cosmetic (and not so cosmetic) differences from the original tzcode library, but diffs in the upstream version should usually be propagated to our version. Here are some notes about that. diff --git a/src/timezone/localtime.c b/src/timezone/localtime.c index e6c1beaf96..154124e49c 100644 --- a/src/timezone/localtime.c +++ b/src/timezone/localtime.c @@ -17,8 +17,9 @@ #include #include "datatype/timestamp.h" -#include "private.h" #include "pgtz.h" + +#include "private.h" #include "tzfile.h" @@ -414,10 +415,10 @@ tzloadbody(char const * name, char *canonname, struct state * sp, bool doextend, { /* * Attempt to reuse existing abbreviations. Without this, - * America/Anchorage would stop working after 2037 when - * TZ_MAX_CHARS is 50, as sp->charcnt equals 42 (for LMT CAT CAWT - * CAPT AHST AHDT YST AKDT AKST) and ts->charcnt equals 10 (for - * AKST AKDT). Reusing means sp->charcnt can stay 42 in this + * America/Anchorage would be right on the edge after 2037 when + * TZ_MAX_CHARS is 50, as sp->charcnt equals 40 (for LMT AST AWT + * APT AHST AHDT YST AKDT AKST) and ts->charcnt equals 10 (for + * AKST AKDT). Reusing means sp->charcnt can stay 40 in this * example. */ int gotabbr = 0; @@ -451,6 +452,17 @@ tzloadbody(char const * name, char *canonname, struct state * sp, bool doextend, if (gotabbr == 2) { sp->charcnt = charcnt; + + /* + * Ignore any trailing, no-op transitions generated by zic as + * they don't help here and can run afoul of bugs in zic 2016j + * or earlier. + */ + while (1 < sp->timecnt + && (sp->types[sp->timecnt - 1] + == sp->types[sp->timecnt - 2])) + sp->timecnt--; + for (i = 0; i < ts->timecnt; i++) if (sp->ats[sp->timecnt - 1] < ts->ats[i]) break; @@ -974,6 +986,8 @@ tzparse(const char *name, struct state * sp, bool lastditch) int yearlim; int timecnt; pg_time_t janfirst; + int32 janoffset = 0; + int yearbeg; ++name; if ((name = getrule(name, &start)) == NULL) @@ -994,8 +1008,23 @@ tzparse(const char *name, struct state * sp, bool lastditch) sp->defaulttype = 0; timecnt = 0; janfirst = 0; - yearlim = EPOCH_YEAR + YEARSPERREPEAT; - for (year = EPOCH_YEAR; year < yearlim; year++) + yearbeg = EPOCH_YEAR; + + do + { + int32 yearsecs + = year_lengths[isleap(yearbeg - 1)] * SECSPERDAY; + + yearbeg--; + if (increment_overflow_time(&janfirst, -yearsecs)) + { + janoffset = -yearsecs; + break; + } + } while (EPOCH_YEAR - YEARSPERREPEAT / 2 < yearbeg); + + yearlim = yearbeg + YEARSPERREPEAT + 1; + for (year = yearbeg; year < yearlim; year++) { int32 starttime = transtime(year, &start, stdoffset), @@ -1020,24 +1049,34 @@ tzparse(const char *name, struct state * sp, bool lastditch) { if (TZ_MAX_TIMES - 2 < timecnt) break; - yearlim = year + YEARSPERREPEAT + 1; sp->ats[timecnt] = janfirst; - if (increment_overflow_time - (&sp->ats[timecnt], starttime)) - break; - sp->types[timecnt++] = reversed; + if (!increment_overflow_time + (&sp->ats[timecnt], + janoffset + starttime)) + sp->types[timecnt++] = reversed; + else if (janoffset) + sp->defaulttype = reversed; sp->ats[timecnt] = janfirst; - if (increment_overflow_time - (&sp->ats[timecnt], endtime)) - break; - sp->types[timecnt++] = !reversed; + if (!increment_overflow_time + (&sp->ats[timecnt], + janoffset + endtime)) + { + sp->types[timecnt++] = !reversed; + yearlim = year + YEARSPERREPEAT + 1; + } + else if (janoffset) + sp->defaulttype = !reversed; } - if (increment_overflow_time(&janfirst, yearsecs)) + if (increment_overflow_time + (&janfirst, janoffset + yearsecs)) break; + janoffset = 0; } sp->timecnt = timecnt; if (!timecnt) sp->typecnt = 1; /* Perpetual DST. */ + else if (YEARSPERREPEAT < year - yearbeg) + sp->goback = sp->goahead = true; } else { diff --git a/src/timezone/pgtz.c b/src/timezone/pgtz.c index b7cfc5f5ac..13ce399033 100644 --- a/src/timezone/pgtz.c +++ b/src/timezone/pgtz.c @@ -17,6 +17,7 @@ #include #include +#include "datatype/timestamp.h" #include "miscadmin.h" #include "pgtz.h" #include "storage/fd.h" @@ -308,14 +309,14 @@ pg_tzset_offset(long gmtoffset) char tzname[128]; snprintf(offsetstr, sizeof(offsetstr), - "%02ld", absoffset / SECSPERHOUR); - absoffset %= SECSPERHOUR; + "%02ld", absoffset / SECS_PER_HOUR); + absoffset %= SECS_PER_HOUR; if (absoffset != 0) { snprintf(offsetstr + strlen(offsetstr), sizeof(offsetstr) - strlen(offsetstr), - ":%02ld", absoffset / SECSPERMIN); - absoffset %= SECSPERMIN; + ":%02ld", absoffset / SECS_PER_MINUTE); + absoffset %= SECS_PER_MINUTE; if (absoffset != 0) snprintf(offsetstr + strlen(offsetstr), sizeof(offsetstr) - strlen(offsetstr), diff --git a/src/timezone/private.h b/src/timezone/private.h index b8533d51e8..f031b17b7e 100644 --- a/src/timezone/private.h +++ b/src/timezone/private.h @@ -67,14 +67,8 @@ extern int unlink(const char *filename); * Finally, some convenience items. */ -#ifndef TYPE_BIT #define TYPE_BIT(type) (sizeof (type) * CHAR_BIT) -#endif /* !defined TYPE_BIT */ - -#ifndef TYPE_SIGNED #define TYPE_SIGNED(type) (((type) -1) < 0) -#endif /* !defined TYPE_SIGNED */ - #define TWOS_COMPLEMENT(t) ((t) ~ (t) 0 < 0) /* @@ -88,7 +82,6 @@ extern int unlink(const char *filename); #define MINVAL(t, b) \ ((t) (TYPE_SIGNED(t) ? - TWOS_COMPLEMENT(t) - MAXVAL(t, b) : 0)) -#ifndef INT_STRLEN_MAXIMUM /* * 302 / 1000 is log10(2.0) rounded up. * Subtract one for the sign bit if the type is signed; @@ -98,7 +91,6 @@ extern int unlink(const char *filename); #define INT_STRLEN_MAXIMUM(type) \ ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + \ 1 + TYPE_SIGNED(type)) -#endif /* !defined INT_STRLEN_MAXIMUM */ /* * INITIALIZE(x) @@ -108,24 +100,70 @@ extern int unlink(const char *filename); #undef _ #define _(msgid) (msgid) -#ifndef YEARSPERREPEAT +/* Handy macros that are independent of tzfile implementation. */ + #define YEARSPERREPEAT 400 /* years before a Gregorian repeat */ -#endif /* !defined YEARSPERREPEAT */ + +#define SECSPERMIN 60 +#define MINSPERHOUR 60 +#define HOURSPERDAY 24 +#define DAYSPERWEEK 7 +#define DAYSPERNYEAR 365 +#define DAYSPERLYEAR 366 +#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) +#define SECSPERDAY ((int32) SECSPERHOUR * HOURSPERDAY) +#define MONSPERYEAR 12 + +#define TM_SUNDAY 0 +#define TM_MONDAY 1 +#define TM_TUESDAY 2 +#define TM_WEDNESDAY 3 +#define TM_THURSDAY 4 +#define TM_FRIDAY 5 +#define TM_SATURDAY 6 + +#define TM_JANUARY 0 +#define TM_FEBRUARY 1 +#define TM_MARCH 2 +#define TM_APRIL 3 +#define TM_MAY 4 +#define TM_JUNE 5 +#define TM_JULY 6 +#define TM_AUGUST 7 +#define TM_SEPTEMBER 8 +#define TM_OCTOBER 9 +#define TM_NOVEMBER 10 +#define TM_DECEMBER 11 + +#define TM_YEAR_BASE 1900 + +#define EPOCH_YEAR 1970 +#define EPOCH_WDAY TM_THURSDAY + +#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) /* - * The Gregorian year averages 365.2425 days, which is 31556952 seconds. + * Since everything in isleap is modulo 400 (or a factor of 400), we know that + * isleap(y) == isleap(y % 400) + * and so + * isleap(a + b) == isleap((a + b) % 400) + * or + * isleap(a + b) == isleap(a % 400 + b % 400) + * This is true even if % means modulo rather than Fortran remainder + * (which is allowed by C89 but not C99). + * We use this to avoid addition overflow problems. */ -#ifndef AVGSECSPERYEAR -#define AVGSECSPERYEAR 31556952L -#endif /* !defined AVGSECSPERYEAR */ +#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400) -#ifndef SECSPERREPEAT -#define SECSPERREPEAT ((int64) YEARSPERREPEAT * (int64) AVGSECSPERYEAR) -#endif /* !defined SECSPERREPEAT */ -#ifndef SECSPERREPEAT_BITS +/* + * The Gregorian year averages 365.2425 days, which is 31556952 seconds. + */ + +#define AVGSECSPERYEAR 31556952L +#define SECSPERREPEAT \ + ((int64) YEARSPERREPEAT * (int64) AVGSECSPERYEAR) #define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */ -#endif /* !defined SECSPERREPEAT_BITS */ #endif /* !defined PRIVATE_H */ diff --git a/src/timezone/strftime.c b/src/timezone/strftime.c index acaba86881..d9a18d49a8 100644 --- a/src/timezone/strftime.c +++ b/src/timezone/strftime.c @@ -1,4 +1,4 @@ -/* Convert a broken-down time stamp to a string. */ +/* Convert a broken-down timestamp to a string. */ /* * Copyright 1989 The Regents of the University of California. @@ -43,7 +43,6 @@ #include #include "private.h" -#include "tzfile.h" struct lc_time_T @@ -451,11 +450,17 @@ _fmt(const char *format, const struct pg_tm * t, char *pt, const char *ptlim, { long diff; char const *sign; + bool negative; if (t->tm_isdst < 0) continue; diff = t->tm_gmtoff; - if (diff < 0) + negative = diff < 0; + if (diff == 0) + { + negative = t->tm_zone[0] == '-'; + } + if (negative) { sign = "-"; diff = -diff; diff --git a/src/timezone/tzfile.h b/src/timezone/tzfile.h index 32d237b827..56a5b43472 100644 --- a/src/timezone/tzfile.h +++ b/src/timezone/tzfile.h @@ -100,56 +100,4 @@ struct tzhead #define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */ -#define SECSPERMIN 60 -#define MINSPERHOUR 60 -#define HOURSPERDAY 24 -#define DAYSPERWEEK 7 -#define DAYSPERNYEAR 365 -#define DAYSPERLYEAR 366 -#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) -#define SECSPERDAY ((int32) SECSPERHOUR * HOURSPERDAY) -#define MONSPERYEAR 12 - -#define TM_SUNDAY 0 -#define TM_MONDAY 1 -#define TM_TUESDAY 2 -#define TM_WEDNESDAY 3 -#define TM_THURSDAY 4 -#define TM_FRIDAY 5 -#define TM_SATURDAY 6 - -#define TM_JANUARY 0 -#define TM_FEBRUARY 1 -#define TM_MARCH 2 -#define TM_APRIL 3 -#define TM_MAY 4 -#define TM_JUNE 5 -#define TM_JULY 6 -#define TM_AUGUST 7 -#define TM_SEPTEMBER 8 -#define TM_OCTOBER 9 -#define TM_NOVEMBER 10 -#define TM_DECEMBER 11 - -#define TM_YEAR_BASE 1900 - -#define EPOCH_YEAR 1970 -#define EPOCH_WDAY TM_THURSDAY - -#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) - -/* - * Since everything in isleap is modulo 400 (or a factor of 400), we know that - * isleap(y) == isleap(y % 400) - * and so - * isleap(a + b) == isleap((a + b) % 400) - * or - * isleap(a + b) == isleap(a % 400 + b % 400) - * This is true even if % means modulo rather than Fortran remainder - * (which is allowed by C89 but not C99). - * We use this to avoid addition overflow problems. - */ - -#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400) - #endif /* !defined TZFILE_H */ diff --git a/src/timezone/zic.c b/src/timezone/zic.c index e1875585df..5fa0a81262 100644 --- a/src/timezone/zic.c +++ b/src/timezone/zic.c @@ -2671,6 +2671,9 @@ outzone(const struct zone * zpfirst, ptrdiff_t zonecount) bool do_extend; char version; ptrdiff_t lastatmax = -1; + zic_t one = 1; + zic_t y2038_boundary = one << 31; + zic_t max_year0; max_abbr_len = 2 + max_format_len + max_abbrvar_len; max_envvar_len = 2 * max_abbr_len + 5 * 9; @@ -2780,12 +2783,13 @@ outzone(const struct zone * zpfirst, ptrdiff_t zonecount) } /* - * For the benefit of older systems, generate data from 1900 through 2037. + * For the benefit of older systems, generate data from 1900 through 2038. */ if (min_year > 1900) min_year = 1900; - if (max_year < 2037) - max_year = 2037; + max_year0 = max_year; + if (max_year < 2038) + max_year = 2038; for (i = 0; i < zonecount; ++i) { /* @@ -2835,7 +2839,12 @@ outzone(const struct zone * zpfirst, ptrdiff_t zonecount) year <= rp->r_hiyear && yearistype(year, rp->r_yrtype); if (rp->r_todo) + { rp->r_temp = rpytime(rp, year); + rp->r_todo + = (rp->r_temp < y2038_boundary + || year <= max_year0); + } } for (;;) { -- cgit v1.2.3