[tz] version information in tz binary file?

Arthur David Olson arthurdavidolson at gmail.com
Tue Sep 10 02:14:58 UTC 2013


I'm guessing that a way to minimize breakage is to end the file with:
    the POSIX string
    any name/value pairs
    a repeat of the POSIX string.
That way folks who look for the POSIX string at the very end of the file
will find it, and folks who look for it after the 64-bit data will too.

    --ado


On Mon, Sep 9, 2013 at 9:04 PM, Paul Eggert <eggert at cs.ucla.edu> wrote:

> Arthur David Olson wrote:
>
> > Adding something such as "2013e" wouldn't exhaust the reserved bytes
>
> Yes, but I anticipate that various distros will want to append
> their own information to the version string, and the reserved
> space is uncomfortably small for that.  And I share Zefram's
> leeriness of making this version information so primary; it's
> really just auxiliary data that does not affect how timestamps
> are represented or interpreted, unlike the version byte.
>
> So how about this idea instead?  As part of tzfile.v3 we allow
> name-value pairs at the end of the file.  One of them can be
> the version, another the zone name, and perhaps we'll think
> of others.  Here's a proposed patch to do this, which I've
> pushed into the experimental version.
>
> From d7680ffd3d43c4da6d9ff21ffb93b6783703a301 Mon Sep 17 00:00:00 2001
> From: Paul Eggert <eggert at cs.ucla.edu>
> Date: Mon, 9 Sep 2013 17:16:37 -0700
> Subject: [PATCH] Add optional meta-information to version-3 format.
>
> * Makefile (ZFLAGS): Add a comment about how to enable meta-info.
> * tzfile.5: Describe meta-information.
> * zic.8: Document new options -n and -o, which cause zic to
> generate meta-info.
> * zic.c: Include <stddef.h>, for ptrdiff_t.
> (genoption, genoptions, genname): New static vars.
> (usage): Summarize new options.
> (addgenoption, writevalue): New function.
> (main, writezone): Add support for new options.
> ---
>  Makefile |  3 +++
>  tzfile.5 | 13 ++++++++++++
>  zic.8    | 14 +++++++++++++
>  zic.c    | 73
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
>  4 files changed, 101 insertions(+), 2 deletions(-)
>
> diff --git a/Makefile b/Makefile
> index 41b6ffc..eccb9da 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -250,6 +250,9 @@ LDFLAGS=    $(LFLAGS)
>  zic=           ./zic
>  ZIC=           $(zic) $(ZFLAGS)
>
> +# Uncomment this to put name and version info into zic output files.
> +#ZFLAGS=       -n -o version='$(VERSION)'
> +
>  # The name of a Posix-compliant `awk' on your system.
>  AWK=           awk
>
> diff --git a/tzfile.5 b/tzfile.5
> index ff1ec63..d609277 100644
> --- a/tzfile.5
> +++ b/tzfile.5
> @@ -154,6 +154,19 @@ First, the hours part of its transition times may be
> signed and range from
>  from 0 through 24.  Second, DST is in effect all year if it starts
>  January 1 at 00:00 and ends December 31 at 24:00 plus the difference
>  between daylight saving and standard time.
> +.PP
> +Also, for version-3-format time zone files, the version-2 header and
> +data are optionally followed by a section containing auxiliary
> +meta-information that is not needed to process time stamps.  This
> +section, if present, consists of the four magic bytes "=TZ\en"
> +followed by zero or more newline-terminated byte strings, each
> +containing a name-value pair separated by "=".  Names consist of ASCII
> +letters, digits and underscores, and start with a letter; duplicate
> +names are not allowed.  Two common names are "name", the Zone name for
> +the data, and "version", the version number.  Values consist of any
> +bytes except NUL, newline, and backslash; however, newline and
> +backslash can represented via the two-byte strings "\en" and "\e\e"
> +respectively.
>  .SH SEE ALSO
>  newctime(3), newtzset(3)
>  .\" This file is in the public domain, so clarified as of
> diff --git a/zic.8 b/zic.8
> index 602c3c9..b1d3348 100644
> --- a/zic.8
> +++ b/zic.8
> @@ -15,6 +15,11 @@ zic \- time zone compiler
>  .B \-l
>  .I localtime
>  ] [
> +.B \-n
> +] [
> +.B \-o
> +.IB name = value
> +] [
>  .B \-p
>  .I posixrules
>  ] [
> @@ -62,6 +67,15 @@ will act as if the input contained a link line of the
> form
>  .ti +.5i
>  Link   \fItimezone\fP          localtime
>  .TP
> +.B "\-n"
> +Store each zone's name into its generated file, as meta-information
> +with the name "name" and value the zone's name.
> +.TP
> +.BI "\-o " name = value
> +Store the given name-value pair into the generated file, as
> +meta-information.  This option can be repeated, once for each distinct
> +name.
> +.TP
>  .BI "\-p " timezone
>  Use the given time zone's rules when handling POSIX-format
>  time zone environment variables.
> diff --git a/zic.c b/zic.c
> index 9939195..eefa1fb 100644
> --- a/zic.c
> +++ b/zic.c
> @@ -9,6 +9,7 @@
>  #include "tzfile.h"
>
>  #include <stdarg.h>
> +#include <stddef.h>
>
>  #define        ZIC_VERSION     '3'
>
> @@ -140,6 +141,9 @@ static int  yearistype(int year, const char * type);
>  static int             charcnt;
>  static int             errors;
>  static const char *    filename;
> +static const char **   genoption;
> +static int             genoptions;
> +static int             genname;
>  static int             leapcnt;
>  static int             leapseen;
>  static zic_t           leapminyear;
> @@ -432,7 +436,8 @@ static _Noreturn void
>  usage(FILE *stream, int status)
>  {
>         (void) fprintf(stream, _("%s: usage is %s \
> -[ --version ] [ --help ] [ -v ] [ -l localtime ] [ -p posixrules ] \\\n\
> +[ --version ] [ --help ] [ -v ] [ -l localtime ]\\\n\
> +\t[ -n ] [ -o name=value ]... [ -p posixrules ] \\\n\
>  \t[ -d directory ] [ -L leapseconds ] [ -y yearistype ] [ filename ...
> ]\n\
>  \n\
>  Report bugs to %s.\n"),
> @@ -446,6 +451,31 @@ static const char *        directory;
>  static const char *    leapsec;
>  static const char *    yitcommand;
>
> +static int
> +addgenoption(char const *option)
> +{
> +       register char const *o = option;
> +       register ptrdiff_t namelen;
> +       register int i;
> +       if (! (isascii (*o) && isalpha(*o)))
> +               return 0;
> +       while (*++o != '=')
> +               if (! (isascii (*o) && (isalnum(*o) || *o == '_')))
> +                       return 0;
> +       namelen = o - option;
> +       if (INT_MAX < namelen)
> +               return 0; /* fprintf won't work.  */
> +       if (namelen == sizeof "name" - 1
> +           && memcmp(option, "name", namelen) == 0)
> +               return 0;
> +       for (i = 0; i < genoptions; i++)
> +               if (strncmp(genoption[i], option, namelen  + 1) == 0)
> +                       return 0;
> +       genoption = erealloc(genoption, (genoptions + 1) * sizeof
> *genoption);
> +       genoption[genoptions++] = option;
> +       return 1;
> +}
> +
>  int
>  main(int argc, char **argv)
>  {
> @@ -476,7 +506,7 @@ main(int argc, char **argv)
>                 } else if (strcmp(argv[i], "--help") == 0) {
>                         usage(stdout, EXIT_SUCCESS);
>                 }
> -       while ((c = getopt(argc, argv, "d:l:p:L:vsy:")) != EOF && c != -1)
> +       while ((c = getopt(argc, argv, "d:l:p:L:no:vsy:")) != EOF && c !=
> -1)
>                 switch (c) {
>                         default:
>                                 usage(stderr, EXIT_FAILURE);
> @@ -500,6 +530,17 @@ _("%s: More than one -l option specified\n"),
>                                         exit(EXIT_FAILURE);
>                                 }
>                                 break;
> +                       case 'n':
> +                               genname = TRUE;
> +                               break;
> +                       case 'o':
> +                               if (!addgenoption(optarg)) {
> +                                       fprintf(stderr,
> +                                               _("%s: %s: invalid -o
> option\n"),
> +                                               progname, optarg);
> +                                       exit(EXIT_FAILURE);
> +                               }
> +                               break;
>                         case 'p':
>                                 if (psxrules == NULL)
>                                         psxrules = optarg;
> @@ -1386,6 +1427,22 @@ is32(const zic_t x)
>  }
>
>  static void
> +writevalue(FILE *fp, char const *v)
> +{
> +       fputc('=', fp);
> +
> +       for (; *v; v++)
> +               if (*v == '\n')
> +                       fprintf(fp, "\\n");
> +               else if (*v == '\\')
> +                       fprintf(fp, "\\\\");
> +               else
> +                       fputc(*v, fp);
> +
> +       fputc('\n', fp);
> +}
> +
> +static void
>  writezone(const char *const name, const char *const string)
>  {
>         register FILE *                 fp;
> @@ -1708,6 +1765,18 @@ writezone(const char *const name, const char *const
> string)
>                                 (void) putc(ttisgmts[i], fp);
>         }
>         (void) fprintf(fp, "\n%s\n", string);
> +       if (genname || genoptions)
> +               fprintf(fp, "=TZ\n");
> +       if (genname) {
> +               fprintf(fp, "name");
> +               writevalue(fp, name);
> +       }
> +       for (i = 0; i < genoptions; i++) {
> +               register char const *v = genoption[i];
> +               register int namelen = strchr(v, '=') - v;
> +               fprintf(fp, "%.*s", namelen, v);
> +               writevalue(fp, v + namelen + 1);
> +       }
>         if (ferror(fp) || fclose(fp)) {
>                 (void) fprintf(stderr, _("%s: Error writing %s\n"),
>                         progname, fullname);
> --
> 1.8.3.1
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mm.icann.org/pipermail/tz/attachments/20130909/97e074f7/attachment-0001.html>


More information about the tz mailing list