[tz] [PROPOSED PATCH 3/3] zic: check more consistently for I/O errors and improve diagnostics
Paul Eggert
eggert at cs.ucla.edu
Tue Aug 19 06:27:26 UTC 2014
* zic.c (warnings): New static var.
(warning): Set it here.
(size_product, growalloc, main): Translate diagnostic.
(verror): Don't increment errors here.
(error): Set it here.
(close_file): New function.
(usage, dolink, infile, writezone): Use it.
(usage): Fit diagnostic in output lines better.
(main): Prefer 'return X;' to 'exit(X);'.
(main, infile, mkdirs): Use 'warning' for warnings.
Check for stderr output error.
(dolink, mkdirs): Don't assume gettext preserves errno.
---
zic.c | 113 ++++++++++++++++++++++++++++++++----------------------------------
1 file changed, 54 insertions(+), 59 deletions(-)
diff --git a/zic.c b/zic.c
index ea63f76..d230663 100644
--- a/zic.c
+++ b/zic.c
@@ -135,6 +135,7 @@ static int yearistype(int year, const char * type);
static int charcnt;
static int errors;
+static int warnings;
static const char * filename;
static int leapcnt;
static int leapseen;
@@ -364,7 +365,7 @@ static ATTRIBUTE_PURE size_t
size_product(size_t nitems, size_t itemsize)
{
if (SIZE_MAX / itemsize < nitems)
- memory_exhausted("size overflow");
+ memory_exhausted(_("size overflow"));
return nitems * itemsize;
}
@@ -389,7 +390,7 @@ growalloc(void *ptr, size_t itemsize, int nitems, int *nitems_alloc)
else {
int amax = INT_MAX < SIZE_MAX ? INT_MAX : SIZE_MAX;
if ((amax - 1) / 3 * 2 < *nitems_alloc)
- memory_exhausted("int overflow");
+ memory_exhausted(_("int overflow"));
*nitems_alloc = *nitems_alloc + (*nitems_alloc >> 1) + 1;
return erealloc(ptr, size_product(*nitems_alloc, itemsize));
}
@@ -429,7 +430,6 @@ verror(const char *const string, va_list args)
fprintf(stderr, _(" (rule from \"%s\", line %d)"),
rfilename, rlinenum);
fprintf(stderr, "\n");
- ++errors;
}
static void ATTRIBUTE_FORMAT((printf, 1, 2))
@@ -439,6 +439,7 @@ error(const char *const string, ...)
va_start(args, string);
verror(string, args);
va_end(args);
+ errors = 1;
}
static void ATTRIBUTE_FORMAT((printf, 1, 2))
@@ -449,19 +450,35 @@ warning(const char *const string, ...)
va_start(args, string);
verror(string, args);
va_end(args);
- --errors;
+ warnings = 1;
+}
+
+static void
+close_file(FILE *stream, 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);
+ exit(EXIT_FAILURE);
+ }
}
static _Noreturn void
usage(FILE *stream, int status)
{
- fprintf(stream, _("%s: usage is %s \
-[ --version ] [ --help ] [ -v ] [ -l localtime ] [ -p posixrules ] \\\n\
-\t[ -d directory ] [ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n\
-\n\
-Report bugs to %s.\n"),
- progname, progname, REPORT_BUGS_TO);
- exit(status);
+ fprintf(stream,
+ _("%s: usage is %s [ --version ] [ --help ] [ -v ] \\\n"
+ "\t[ -l localtime ] [ -p posixrules ] [ -d directory ] \\\n"
+ "\t[ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n\n"
+ "Report bugs to %s.\n"),
+ progname, progname, REPORT_BUGS_TO);
+ if (status == EXIT_SUCCESS)
+ close_file(stream, NULL);
+ exit(status);
}
static const char * psxrules;
@@ -491,12 +508,13 @@ main(int argc, char **argv)
if (TYPE_BIT(zic_t) < 64) {
fprintf(stderr, "%s: %s\n", progname,
_("wild compilation-time specification of zic_t"));
- exit(EXIT_FAILURE);
+ return EXIT_FAILURE;
}
for (i = 1; i < argc; ++i)
if (strcmp(argv[i], "--version") == 0) {
printf("zic %s%s\n", PKGVERSION, TZVERSION);
- exit(EXIT_SUCCESS);
+ close_file(stdout, NULL);
+ return EXIT_SUCCESS;
} else if (strcmp(argv[i], "--help") == 0) {
usage(stdout, EXIT_SUCCESS);
}
@@ -511,7 +529,7 @@ main(int argc, char **argv)
fprintf(stderr,
_("%s: More than one -d option specified\n"),
progname);
- exit(EXIT_FAILURE);
+ return EXIT_FAILURE;
}
break;
case 'l':
@@ -521,7 +539,7 @@ _("%s: More than one -d option specified\n"),
fprintf(stderr,
_("%s: More than one -l option specified\n"),
progname);
- exit(EXIT_FAILURE);
+ return EXIT_FAILURE;
}
break;
case 'p':
@@ -531,7 +549,7 @@ _("%s: More than one -l option specified\n"),
fprintf(stderr,
_("%s: More than one -p option specified\n"),
progname);
- exit(EXIT_FAILURE);
+ return EXIT_FAILURE;
}
break;
case 'y':
@@ -541,7 +559,7 @@ _("%s: More than one -p option specified\n"),
fprintf(stderr,
_("%s: More than one -y option specified\n"),
progname);
- exit(EXIT_FAILURE);
+ return EXIT_FAILURE;
}
break;
case 'L':
@@ -551,14 +569,14 @@ _("%s: More than one -y option specified\n"),
fprintf(stderr,
_("%s: More than one -L option specified\n"),
progname);
- exit(EXIT_FAILURE);
+ return EXIT_FAILURE;
}
break;
case 'v':
noise = TRUE;
break;
case 's':
- printf("%s: -s ignored\n", progname);
+ warning(_("-s ignored\n"));
break;
}
if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
@@ -576,7 +594,7 @@ _("%s: More than one -L option specified\n"),
for (i = optind; i < argc; ++i)
infile(argv[i]);
if (errors)
- exit(EXIT_FAILURE);
+ return EXIT_FAILURE;
associate();
for (i = 0; i < nzones; i = j) {
/*
@@ -599,14 +617,16 @@ _("%s: More than one -L option specified\n"),
warning(_("link to link"));
}
if (lcltime != NULL) {
- eat("command line", 1);
+ eat(_("command line"), 1);
dolink(lcltime, TZDEFAULT);
}
if (psxrules != NULL) {
- eat("command line", 1);
+ eat(_("command line"), 1);
dolink(psxrules, TZDEFRULES);
}
- return (errors == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+ if (warnings && (ferror(stderr) || fclose(stderr) != 0))
+ return EXIT_FAILURE;
+ return errors ? EXIT_FAILURE : EXIT_SUCCESS;
}
static void
@@ -695,9 +715,9 @@ dolink(const char *const fromfield, const char *const tofield)
*/
fromisdir = itsdir(fromname);
if (fromisdir) {
- int err = fromisdir < 0 ? errno : EPERM;
+ char const *e = strerror(fromisdir < 0 ? errno : EPERM);
fprintf(stderr, _("%s: link from %s failed: %s"),
- progname, fromname, strerror(err));
+ progname, fromname, e);
exit(EXIT_FAILURE);
}
if (itsdir(toname) <= 0)
@@ -753,18 +773,8 @@ warning(_("hard link failed, symbolic link used"));
}
while ((c = getc(fp)) != EOF)
putc(c, tp);
- if (ferror(fp) || fclose(fp)) {
- fprintf(stderr,
- _("%s: Error reading %s\n"),
- progname, fromname);
- exit(EXIT_FAILURE);
- }
- if (ferror(tp) || fclose(tp)) {
- fprintf(stderr,
- _("%s: Error writing %s\n"),
- progname, toname);
- exit(EXIT_FAILURE);
- }
+ close_file(fp, fromname);
+ close_file(tp, toname);
warning(_("link failed, copy used"));
}
}
@@ -981,7 +991,7 @@ infile(const char *name)
break;
case LC_LEAP:
if (name != leapsec)
- fprintf(stderr,
+ warning(
_("%s: Leap line in non leap seconds file %s\n"),
progname, name);
else inleap(fields, nfields);
@@ -996,18 +1006,7 @@ _("%s: panic: Invalid l_value %d\n"),
}
free(fields);
}
- if (ferror(fp)) {
- fprintf(stderr, _("%s: Error reading %s\n"),
- progname, filename);
- exit(EXIT_FAILURE);
- }
- if (fp != stdin && fclose(fp)) {
- const char *e = strerror(errno);
-
- fprintf(stderr, _("%s: Error closing %s: %s\n"),
- progname, filename, e);
- exit(EXIT_FAILURE);
- }
+ close_file(fp, filename);
if (wantcont)
error(_("expected continuation line not found"));
}
@@ -1850,11 +1849,7 @@ writezone(const char *const name, const char *const string, char version)
putc(ttisgmts[i], fp);
}
fprintf(fp, "\n%s\n", string);
- if (ferror(fp) || fclose(fp)) {
- fprintf(stderr, _("%s: Error writing %s\n"),
- progname, fullname);
- exit(EXIT_FAILURE);
- }
+ close_file(fp, fullname);
free(ats);
}
@@ -2920,10 +2915,10 @@ mkdirs(char *argname)
if (mkdir(name, MKDIR_UMASK) != 0) {
int err = errno;
if (itsdir(name) <= 0) {
- fprintf(stderr,
- _("%s: Can't create directory"
- " %s: %s\n"),
- progname, name, strerror(err));
+ char const *e = strerror(err);
+ warning(_("%s: Can't create directory"
+ " %s: %s\n"),
+ progname, name, e);
free(name);
return -1;
}
--
1.9.1
More information about the tz
mailing list