Sync our copy of the timezone library with IANA release tzcode2020c.
This changes zic's default output format from "-b fat" to "-b slim". We were already using "slim" in v13/HEAD, so those branches drop the explicit -b switch in the Makefiles. Instead, add an explicit "-b fat" in v12 and before, so that we don't change the output file format in those branches. (This is perhaps excessively conservative, but we decided not to do so in a12079109, and I'll stick with that.) Other non-cosmetic changes are to drop support for zic's long-obsolete "-y" switch, and to ensure that strftime() does not change errno unless it fails. As usual with tzcode changes, back-patch to all supported branches.
This commit is contained in:
parent
3d338a46a4
commit
e0cf5e9b22
@ -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 $@
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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 = $_;
|
||||
|
Loading…
x
Reference in New Issue
Block a user