[tz] [PATCH] Support building zic.exe and zdump.exe natively on Windows with Visual Studio nmake.

Manuela Friedrich Manuela.Friedrich at actian.com
Mon Feb 12 14:26:05 UTC 2018

Hello Paul,

Right, I see that time.h includes time.inl which contains

_CRT_INSECURE_DEPRECATE(localtime_s) static __inline struct tm * __CRTDECL localtime(const time_t * _Time)
#pragma warning( push )
#pragma warning( disable : 4996 )
    return _localtime64(_Time);
#pragma warning( pop )

However this did not compile with Visual Studio because if I include time.h header than usage of native localtime is expected and MS localtime function definition is pulled into the code, however, if you want us to use your version of localtime then prototype has to be defined in your header.  Compilation error for time.h header inclusion is as follows:

localtime.c(1540) : error C2084: function 'tm *localtime(const time_t *)' already has a body
        C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\INCLUDE\time.inl(112) : see previous definition of 'localtime'
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\BIN\x86_amd64\cl.EXE"' : return code '0x2'

To avoid this error I excluded time.inl by using -D_INC_TIME_INL CFLAG, but then the problem with the missing prototype prevented zdump from working properly.
Can you add this to private.h? Maybe with a new macro if you prefer that?

For zdump -v we cannot use UNC paths and when we tried with -DTZDIR='\0' tzloadbody still created a path starting with leading slash, like /c:\mydir.
So we added code that checks if TZDIR is not empty and only then applies the the leading slash.
Is that an acceptable alternative?

localtime.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/localtime.c b/localtime.c
index 6f5aa76..be63de4 100644
--- a/localtime.c
+++ b/localtime.c
@@ -357,7 +357,7 @@ union input_buffer {

/* TZDIR with a trailing '/' rather than a trailing '\0'.  */
-static char const tzdirslash[sizeof TZDIR] = TZDIR "/";
+static char tzdirslash[sizeof TZDIR] = {TZDIR} ;

/* Local storage needed for 'tzloadbody'.  */
union local_storage {
@@ -389,6 +389,8 @@ tzloadbody(char const *name, struct state *sp, bool doextend,
                register bool doaccess;
                register union input_buffer *up = &lsp->u.u;
                register int tzheadsize = sizeof (struct tzhead);
+             if (*tzdirslash)
+                             strcat(tzdirslash, "/");

               sp->goback = sp->goahead = false;

@@ -410,8 +412,10 @@ tzloadbody(char const *name, struct state *sp, bool doextend,
                                   would pull in stdio (and would fail if the
                                   resulting string length exceeded INT_MAX!).  */
                                memcpy(lsp->fullname, tzdirslash, sizeof tzdirslash);
-                              strcpy(lsp->fullname + sizeof tzdirslash, name);
+                             if (*tzdirslash)
+                                 strcpy(lsp->fullname + sizeof tzdirslash, name);
+                             else
+                                 strcpy(lsp->fullname, name);
                                /* Set doaccess if '.' (as in "../") shows up in name.  */
                                if (strchr(name, '.'))
                                                doaccess = true;

The issue is that zdump is included for customers to verify their timezone files and it should be able to handle any type of path including a full path to the file.  As a result, we need to get this code to run with a full path or at least recognize it and not corrupt it.

We realize you are reluctant to take any windows specific changes due to lack of resources to support this going forward, however, we intend to implement continuous integration to ensure that the latest code is always tested on Windows and any issues that are encountered are fixed as soon as possible and submitted back to iana.org.  As a result, we really hope you will work with us to ensure this helpful package can be expanded to encapsulate support on Windows going forward and open up its usage to a wider audience.  We intend to support iana.org community by ensuring the highest quality of the package enclosed with our products.

Manuela Friedrich

From: Paul Eggert [mailto:eggert at cs.ucla.edu]
Sent: Donnerstag, 8. Februar 2018 06:54
To: Manuela Friedrich <Manuela.Friedrich at actian.com>; Time Zone Mailing List <tz at iana.org>
Subject: Re: [tz] [PATCH] Support building zic.exe and zdump.exe natively on Windows with Visual Studio nmake.

Manuela Friedrich wrote:
> In zdump localtime_r() was calling localtime() but it crashed after the return from localtime because there was no prototype for localtime

Why not? zdump.c includes private.h, which includes time.h, and that should
should declare a prototype for localtime, according to this page:


> Therefore it is crucial for us to have the dos specifier check in tzloadbody().
> This change won’t affect the behaviour on Unix and using a full path works fine on Unix.

It does affect the behavior on Unix, as file names like "a:b" are valid relative
file names whereas the proposed code would treat them as absolute.

Can you use UNC names instead? Perhaps something starting with // will do the
trick. Or if that doesn't work, perhaps you can set TZDIR=/ when running 'make',
and then cd to the appropriate drive root before running zdump and/or zic and
then use a path relative to that drive root. At any rate, I'm not sure it's a
good idea for portable code to worry about these ins and outs of MS-Windows file
name conventions.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mm.icann.org/pipermail/tz/attachments/20180212/66f8d5f6/attachment-0001.html>

More information about the tz mailing list