diff --git a/src/timezone/Makefile b/src/timezone/Makefile index 715b63cee0..2b5d8ecbef 100644 --- a/src/timezone/Makefile +++ b/src/timezone/Makefile @@ -56,7 +56,7 @@ zic: $(ZICOBJS) | submake-libpgport install: all installdirs ifeq (,$(with_system_tzdata)) - $(ZIC) -d '$(DESTDIR)$(datadir)/timezone' -b slim $(ZIC_OPTIONS) $(TZDATAFILES) + $(ZIC) -d '$(DESTDIR)$(datadir)/timezone' $(ZIC_OPTIONS) $(TZDATAFILES) endif $(MAKE) -C tznames $@ diff --git a/src/timezone/README b/src/timezone/README index 8af4444932..10aeedce92 100644 --- a/src/timezone/README +++ b/src/timezone/README @@ -55,7 +55,7 @@ match properly on the old version. Time Zone code ============== -The code in this directory is currently synced with tzcode release 2020a. +The code in this directory is currently synced with tzcode release 2020c. 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/strftime.c b/src/timezone/strftime.c index 4b942c393a..dd6c7db869 100644 --- a/src/timezone/strftime.c +++ b/src/timezone/strftime.c @@ -128,12 +128,22 @@ size_t pg_strftime(char *s, size_t maxsize, const char *format, const struct pg_tm *t) { char *p; + int saved_errno = errno; enum warn warn = IN_NONE; p = _fmt(format, t, s, s + maxsize, &warn); - if (p == s + maxsize) + if (!p) + { + errno = EOVERFLOW; return 0; + } + if (p == s + maxsize) + { + errno = ERANGE; + return 0; + } *p = '\0'; + errno = saved_errno; return p - s; } diff --git a/src/timezone/zic.c b/src/timezone/zic.c index 10c5b4bfb5..a1c64051f7 100644 --- a/src/timezone/zic.c +++ b/src/timezone/zic.c @@ -37,10 +37,6 @@ typedef int64 zic_t; #define MKDIR_UMASK 0755 #endif #endif -#ifndef AT_SYMLINK_FOLLOW -#define linkat(fromdir, from, todir, to, flag) \ - (itssymlink(from) ? (errno = ENOTSUP, -1) : link(from, to)) -#endif /* Port to native MS-Windows and to ancient UNIX. */ #if !defined S_ISDIR && defined S_IFDIR && defined S_IFMT #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) @@ -66,7 +62,6 @@ struct rule zic_t r_loyear; /* for example, 1986 */ zic_t r_hiyear; /* for example, 1986 */ - const char *r_yrtype; bool r_lowasnum; bool r_hiwasnum; @@ -116,7 +111,11 @@ struct zone zic_t z_untiltime; }; -extern int link(const char *fromname, const char *toname); +extern int link(const char *target, const char *linkname); +#ifndef AT_SYMLINK_FOLLOW +#define linkat(targetdir, target, linknamedir, linkname, flag) \ + (itssymlink(target) ? (errno = ENOTSUP, -1) : link(target, linkname)) +#endif static void memory_exhausted(const char *msg) pg_attribute_noreturn(); static void verror(const char *string, va_list args) pg_attribute_printf(1, 0); @@ -154,7 +153,6 @@ static void rulesub(struct rule *rp, 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(zic_t year, const char *type); /* Bound on length of what %z can expand to. */ enum @@ -253,8 +251,8 @@ static int typecnt; * Which fields are which on a Link line. */ -#define LF_FROM 1 -#define LF_TO 2 +#define LF_TARGET 1 +#define LF_LINKNAME 2 #define LINK_FIELDS 3 /* @@ -292,8 +290,8 @@ struct link { const char *l_filename; lineno_t l_linenum; - const char *l_from; - const char *l_to; + const char *l_target; + const char *l_linkname; }; static struct link *links; @@ -634,11 +632,9 @@ static const char *lcltime; static const char *directory; static const char *leapsec; static const char *tzdefault; -static const char *yitcommand; /* -1 if the TZif output file should be slim, 0 if default, 1 if the - output should be fat for backward compatibility. Currently the - default is fat, although this may change. */ + output should be fat for backward compatibility. The default is slim. */ static int bloat; static bool @@ -648,7 +644,7 @@ want_bloat(void) } #ifndef ZIC_BLOAT_DEFAULT -#define ZIC_BLOAT_DEFAULT "fat" +#define ZIC_BLOAT_DEFAULT "slim" #endif int @@ -747,18 +743,7 @@ main(int argc, char **argv) tzdefault = optarg; break; case 'y': - if (yitcommand == NULL) - { - warning(_("-y is obsolescent")); - yitcommand = strdup(optarg); - } - else - { - fprintf(stderr, - _("%s: More than one -y option specified\n"), - progname); - return EXIT_FAILURE; - } + warning(_("-y ignored")); break; case 'L': if (leapsec == NULL) @@ -807,8 +792,6 @@ main(int argc, char **argv) directory = "data"; if (tzdefault == NULL) tzdefault = TZDEFAULT; - if (yitcommand == NULL) - yitcommand = "yearistype"; if (optind < argc && leapsec != NULL) { @@ -838,11 +821,11 @@ 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, false); + dolink(links[i].l_target, links[i].l_linkname, false); if (noise) for (j = 0; j < nlinks; ++j) - if (strcmp(links[i].l_to, - links[j].l_from) == 0) + if (strcmp(links[i].l_linkname, + links[j].l_target) == 0) warning(_("link to link")); } if (lcltime != NULL) @@ -953,7 +936,7 @@ namecheck(const char *name) */ #ifdef HAVE_SYMLINK static char * -relname(char const *from, char const *to) +relname(char const *target, char const *linkname) { size_t i, taillen, @@ -961,26 +944,26 @@ relname(char const *from, char const *to) size_t dir_len = 0, dotdots = 0, linksize = SIZE_MAX; - char const *f = from; + char const *f = target; char *result = NULL; - if (*to == '/') + if (*linkname == '/') { /* Make F absolute too. */ size_t len = strlen(directory); bool needslash = len && directory[len - 1] != '/'; - linksize = len + needslash + strlen(from) + 1; + linksize = len + needslash + strlen(target) + 1; f = result = emalloc(linksize); strcpy(result, directory); result[len] = '/'; - strcpy(result + len + needslash, from); + strcpy(result + len + needslash, target); } - for (i = 0; f[i] && f[i] == to[i]; i++) + for (i = 0; f[i] && f[i] == linkname[i]; i++) if (f[i] == '/') dir_len = i + 1; - for (; to[i]; i++) - dotdots += to[i] == '/' && to[i - 1] != '/'; + for (; linkname[i]; i++) + dotdots += linkname[i] == '/' && linkname[i - 1] != '/'; taillen = strlen(f + dir_len); dotdotetcsize = 3 * dotdots + taillen + 1; if (dotdotetcsize <= linksize) @@ -998,62 +981,65 @@ relname(char const *from, char const *to) /* 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) +hardlinkerr(char const *target, char const *linkname) { - int r = linkat(AT_FDCWD, from, AT_FDCWD, to, AT_SYMLINK_FOLLOW); + int r = linkat(AT_FDCWD, target, AT_FDCWD, linkname, AT_SYMLINK_FOLLOW); return r == 0 ? 0 : errno; } static void -dolink(char const *fromfield, char const *tofield, bool staysymlink) +dolink(char const *target, char const *linkname, bool staysymlink) { - bool todirs_made = false; + bool remove_only = strcmp(target, "-") == 0; + bool linkdirs_made = false; int link_errno; /* * We get to be careful here since there's a fair chance of root running * us. */ - if (itsdir(fromfield)) + if (!remove_only && itsdir(target)) { - fprintf(stderr, _("%s: link from %s/%s failed: %s\n"), - progname, directory, fromfield, strerror(EPERM)); + fprintf(stderr, _("%s: linking target %s/%s failed: %s\n"), + progname, directory, target, strerror(EPERM)); exit(EXIT_FAILURE); } if (staysymlink) - staysymlink = itssymlink(tofield); - if (remove(tofield) == 0) - todirs_made = true; + staysymlink = itssymlink(linkname); + if (remove(linkname) == 0) + linkdirs_made = true; else if (errno != ENOENT) { char const *e = strerror(errno); fprintf(stderr, _("%s: Can't remove %s/%s: %s\n"), - progname, directory, tofield, e); + progname, directory, linkname, e); exit(EXIT_FAILURE); } - link_errno = staysymlink ? ENOTSUP : hardlinkerr(fromfield, tofield); - if (link_errno == ENOENT && !todirs_made) + if (remove_only) + return; + link_errno = staysymlink ? ENOTSUP : hardlinkerr(target, linkname); + if (link_errno == ENOENT && !linkdirs_made) { - mkdirs(tofield, true); - todirs_made = true; - link_errno = hardlinkerr(fromfield, tofield); + mkdirs(linkname, true); + linkdirs_made = true; + link_errno = hardlinkerr(target, linkname); } if (link_errno != 0) { #ifdef HAVE_SYMLINK - 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; + bool absolute = *target == '/'; + char *linkalloc = absolute ? NULL : relname(target, linkname); + char const *contents = absolute ? target : linkalloc; + int symlink_errno = symlink(contents, linkname) == 0 ? 0 : errno; - if (!todirs_made + if (!linkdirs_made && (symlink_errno == ENOENT || symlink_errno == ENOTSUP)) { - mkdirs(tofield, true); + mkdirs(linkname, true); if (symlink_errno == ENOENT) - symlink_errno = symlink(contents, tofield) == 0 ? 0 : errno; + symlink_errno = symlink(contents, linkname) == 0 ? 0 : errno; } free(linkalloc); if (symlink_errno == 0) @@ -1069,28 +1055,28 @@ dolink(char const *fromfield, char const *tofield, bool staysymlink) *tp; int c; - fp = fopen(fromfield, "rb"); + fp = fopen(target, "rb"); if (!fp) { char const *e = strerror(errno); fprintf(stderr, _("%s: Can't read %s/%s: %s\n"), - progname, directory, fromfield, e); + progname, directory, target, e); exit(EXIT_FAILURE); } - tp = fopen(tofield, "wb"); + tp = fopen(linkname, "wb"); if (!tp) { char const *e = strerror(errno); fprintf(stderr, _("%s: Can't create %s/%s: %s\n"), - progname, directory, tofield, e); + progname, directory, linkname, e); exit(EXIT_FAILURE); } while ((c = getc(fp)) != EOF) putc(c, tp); - close_file(fp, directory, fromfield); - close_file(tp, directory, tofield); + close_file(fp, directory, target); + close_file(tp, directory, linkname); if (link_errno != ENOTSUP) warning(_("copy used because hard link failed: %s"), strerror(link_errno)); @@ -1806,17 +1792,17 @@ inlink(char **fields, int nfields) error(_("wrong number of fields on Link line")); return; } - if (*fields[LF_FROM] == '\0') + if (*fields[LF_TARGET] == '\0') { - error(_("blank FROM field on Link line")); + error(_("blank TARGET field on Link line")); return; } - if (!namecheck(fields[LF_TO])) + if (!namecheck(fields[LF_LINKNAME])) return; l.l_filename = filename; l.l_linenum = linenum; - l.l_from = ecpyalloc(fields[LF_FROM]); - l.l_to = ecpyalloc(fields[LF_TO]); + l.l_target = ecpyalloc(fields[LF_TARGET]); + l.l_linkname = ecpyalloc(fields[LF_LINKNAME]); links = growalloc(links, sizeof *links, nlinks, &nlinks_alloc); links[nlinks++] = l; } @@ -1932,18 +1918,11 @@ rulesub(struct rule *rp, const char *loyearp, const char *hiyearp, error(_("starting year greater than ending year")); return; } - if (*typep == '\0') - rp->r_yrtype = NULL; - else + if (*typep != '\0') { - if (rp->r_loyear == rp->r_hiyear) - { - error(_("typed single year")); - return; - } - warning(_("year type \"%s\" is obsolete; use \"-\" instead"), - typep); - rp->r_yrtype = ecpyalloc(typep); + error(_("year type \"%s\" is unsupported; use \"-\" instead"), + typep); + return; } /* @@ -2848,8 +2827,6 @@ stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount) rp = &zp->z_rules[i]; if (rp->r_hiwasnum || rp->r_hiyear != ZIC_MAX) continue; - if (rp->r_yrtype != NULL) - continue; if (!rp->r_isdst) { if (stdrp == NULL) @@ -3145,7 +3122,8 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount) /* * Mark which rules to do in the current year. For those to - * do, calculate rpytime(rp, year); + * do, calculate rpytime(rp, year); The former TYPE field was + * also considered here. */ for (j = 0; j < zp->z_nrules; ++j) { @@ -3153,8 +3131,7 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount) eats(zp->z_filename, zp->z_linenum, rp->r_filename, rp->r_linenum); rp->r_todo = year >= rp->r_loyear && - year <= rp->r_hiyear && - yearistype(year, rp->r_yrtype); + year <= rp->r_hiyear; if (rp->r_todo) { rp->r_temp = rpytime(rp, year); @@ -3474,54 +3451,6 @@ 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(zic_t year, const char *type) -{ - char *buf; - char *b; - int result; - - if (type == NULL || *type == '\0') - return true; - 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)) - { - int status = WEXITSTATUS(result); - - if (status <= 1) - { - free(buf); - return status == 0; - } - } - error(_("Wild result from command execution")); - fprintf(stderr, _("%s: command was '%s', result was %d\n"), - progname, buf, result); - exit(EXIT_FAILURE); -} - /* Is A a space character in the C locale? */ static bool is_space(char a) diff --git a/src/tools/msvc/Install.pm b/src/tools/msvc/Install.pm index b6d0cfd39b..ea3af48777 100644 --- a/src/tools/msvc/Install.pm +++ b/src/tools/msvc/Install.pm @@ -369,7 +369,7 @@ sub GenerateTimezoneFiles print "Generating timezone files..."; my @args = ( - "$conf/zic/zic", '-d', "$target/share/timezone", '-b', 'slim'); + "$conf/zic/zic", '-d', "$target/share/timezone"); foreach (@tzfiles) { my $tzfile = $_;