[tz] "zic -l" complains about "empty component" in /etc/localtime
Paul Eggert
eggert at cs.ucla.edu
Tue May 19 08:27:21 UTC 2015
Thanks for the bug report. I installed the attached more-elaborate patch into
the experimental version on github. It should fix the problem in a different way.
-------------- next part --------------
From fc861a9e137c63e1b0d562ad09d0dd5f4d8e798f Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert at cs.ucla.edu>
Date: Tue, 19 May 2015 01:24:30 -0700
Subject: [PROPOSED PATCH] Fix zic -l problem with /etc/localtime
Problem reported by Leonardo Chiquitto in:
http://mm.icann.org/pipermail/tz/2015-May/022276.html
Apparently his zic was built with -DTZDEFAULT=\"/etc/localtime\".
* NEWS: Document this.
* zic.c (verror): Don't dump core if filename is NULL.
(main, infile, mkdirs): Omit unnecessary trailing \n in diagnostic.
(componentcheck, namecheck): Now returns bool. All callers changed.
(componentcheck): Make the diagnostics more understandable.
Don't exit on error, so that the user can see multiple errors.
(dolink, writezone): Don't namecheck here.
(inzsub, inlink): Do it here instead.
This generates better diagnostics, and avoids the bug, since
it doesn't apply namecheck to TZDEFAULT or to TZDEFRULES.
---
NEWS | 4 ++++
zic.c | 74 ++++++++++++++++++++++++++++++++++++-------------------------------
2 files changed, 44 insertions(+), 34 deletions(-)
diff --git a/NEWS b/NEWS
index d69a98c..fd9b5ec 100644
--- a/NEWS
+++ b/NEWS
@@ -20,6 +20,10 @@ Unreleased, experimental changes
tzselect no longer mishandles Dominica, fixing a bug introduced
in Release 2014f. (Problem reported by Owen Leibman.)
+ zic -l no longer fails when compiled with -DTZDEFAULT=\"/etc/localtime\".
+ This fixes a bug introduced in Release 2014f.
+ (Problem reported by Leonardo Chiquitto.)
+
Release 2015d - 2015-04-24 08:09:46 -0700
diff --git a/zic.c b/zic.c
index 52b45ad..f51fc48 100644
--- a/zic.c
+++ b/zic.c
@@ -443,7 +443,8 @@ verror(const char *const string, va_list args)
** zic ... 2>&1 | error -t "*" -v
** on BSD systems.
*/
- fprintf(stderr, _("\"%s\", line %d: "), filename, linenum);
+ if (filename)
+ fprintf(stderr, _("\"%s\", line %d: "), filename, linenum);
vfprintf(stderr, string, args);
if (rfilename != NULL)
fprintf(stderr, _(" (rule from \"%s\", line %d)"),
@@ -595,7 +596,7 @@ _("%s: More than one -L option specified\n"),
noise = true;
break;
case 's':
- warning(_("-s ignored\n"));
+ warning(_("-s ignored"));
break;
}
if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
@@ -648,36 +649,43 @@ _("%s: More than one -L option specified\n"),
return errors ? EXIT_FAILURE : EXIT_SUCCESS;
}
-static void
+static bool
componentcheck(char const *name, char const *component,
char const *component_end)
{
enum { component_len_max = 14 };
size_t component_len = component_end - component;
if (component_len == 0) {
- fprintf(stderr, _("%s: file name '%s' contains empty component"),
- progname, name);
- exit(EXIT_FAILURE);
+ if (!*name)
+ error (_("empty file name"));
+ else
+ error (_(component == name
+ ? "file name '%s' begins with '/'"
+ : *component_end
+ ? "file name '%s' contains '//'"
+ : "file name '%s' ends with '/'"),
+ name);
+ return false;
}
if (0 < component_len && component_len <= 2
&& component[0] == '.' && component_end[-1] == '.') {
- fprintf(stderr, _("%s: file name '%s' contains"
- " '%.*s' component"),
- progname, name, (int) component_len, component);
- exit(EXIT_FAILURE);
+ error(_("file name '%s' contains '%.*s' component"),
+ name, (int) component_len, component);
+ return false;
}
- if (!noise)
- return;
- if (0 < component_len && component[0] == '-')
- warning(_("file name '%s' component contains leading '-'"),
- name);
- if (component_len_max < component_len)
- warning(_("file name '%s' contains overlength component"
- " '%.*s...'"),
- name, component_len_max, component);
+ if (noise) {
+ if (0 < component_len && component[0] == '-')
+ warning(_("file name '%s' component contains leading '-'"),
+ name);
+ if (component_len_max < component_len)
+ warning(_("file name '%s' contains overlength component"
+ " '%.*s...'"),
+ name, component_len_max, component);
+ }
+ return true;
}
-static void
+static bool
namecheck(const char *name)
{
register char const *cp;
@@ -701,14 +709,14 @@ namecheck(const char *name)
? _("file name '%s' contains byte '%c'")
: _("file name '%s' contains byte '\\%o'")),
name, c);
- return;
}
if (c == '/') {
- componentcheck(name, component, cp);
+ if (!componentcheck(name, component, cp))
+ return false;
component = cp + 1;
}
}
- componentcheck(name, component, cp);
+ return componentcheck(name, component, cp);
}
static char *
@@ -733,7 +741,6 @@ dolink(const char *const fromfield, const char *const tofield)
register char * toname;
register int fromisdir;
- namecheck(tofield);
fromname = relname(directory, fromfield);
toname = relname(directory, tofield);
/*
@@ -1020,9 +1027,9 @@ infile(const char *name)
break;
case LC_LEAP:
if (name != leapsec)
- warning(
-_("%s: Leap line in non leap seconds file %s\n"),
- progname, name);
+ warning(_("%s: Leap line in non leap"
+ " seconds file %s"),
+ progname, name);
else inleap(fields, nfields);
wantcont = false;
break;
@@ -1178,7 +1185,9 @@ inzsub(char **fields, int nfields, bool iscont)
i_untilday = ZFC_TILDAY;
i_untiltime = ZFC_TILTIME;
z.z_name = NULL;
- } else {
+ } else if (!namecheck(fields[ZF_NAME]))
+ return false;
+ else {
i_gmtoff = ZF_GMTOFF;
i_rule = ZF_RULE;
i_format = ZF_FORMAT;
@@ -1354,10 +1363,8 @@ inlink(register char **const fields, const int nfields)
error(_("blank FROM field on Link line"));
return;
}
- if (*fields[LF_TO] == '\0') {
- error(_("blank TO field on Link line"));
- return;
- }
+ if (! namecheck(fields[LF_TO]))
+ return;
l.l_filename = filename;
l.l_linenum = linenum;
l.l_from = ecpyalloc(fields[LF_FROM]);
@@ -1587,7 +1594,6 @@ writezone(const char *const name, const char *const string, char version)
void *typesptr = ats + timecnt;
unsigned char *types = typesptr;
- namecheck(name);
/*
** Sort.
*/
@@ -2952,7 +2958,7 @@ mkdirs(char *argname)
if (itsdir(name) <= 0) {
char const *e = strerror(err);
warning(_("%s: Can't create directory"
- " %s: %s\n"),
+ " %s: %s"),
progname, name, e);
free(name);
return false;
--
2.1.0
More information about the tz
mailing list