File tzcode-revert-03-39fd078a6.patch of Package timezone.2231

commit 39fd078a694fa762de5ae7efceca1dbfb7be94b3
Author: Paul Eggert <eggert@cs.ucla.edu>
Date:   Fri Feb 26 03:33:54 2016 -0800

    Port better to MS-Windows
    
    Problems reported by Ian Abbott in:
    http://mm.icann.org/pipermail/tz/2016-February/023286.html
    http://mm.icann.org/pipermail/tz/2016-February/023287.html
    * Makefile (CFLAGS): Add comment about new -D options.
    * date.c (environ, optarg, optind, tzname):
    * private.h (asctime_r, timezone, daylight, altzone):
    * strftime.c (tzname):
    * zdump.c (environ, getopt, optarg, optind, tzname):
    * zic.c (getopt, link, optarg, optind):
    Do not declare if HAVE_POSIX_DECLS, to avoid collisions with
    system declarations, which is a problem with MS-Windows
    and tzname and the dllimport attribute.
    * date.c, zdump.c (tzname): Do not specify size, as POSIX doesn’t.
    * private.h (HAVE_POSIX_DECLS): Default to 1.
    (ENOTSUP): Default to EINVAL.
    * zic.c: If HAVE_DIRECT_H, include direct.h and io.h and
    define a mkdir macro, for MS-Windows.
    (link, symlink): Set errno to ENOTSUP in the substitutes.
    (dolink): Don’t complain merely because link and/or
    symlink is not supported.  Be a bit more economical and robust
    about checking for directories and existing destinations.
    Report errno-related string on link failures.
    (itsdir): Work correctly even if a directory has a timestamp that
    is out of time_t range, so that stat fails with errno ==
    EOVERFLOW.
    (writezone): Don’t remove files we can’t stat.

diff --git a/Makefile b/Makefile
index 568f7f6..20c2c98 100644
--- a/Makefile
+++ b/Makefile
@@ -106,6 +106,7 @@ LDLIBS=
 
 # Add the following to the end of the "CFLAGS=" line as needed.
 #  -DBIG_BANG=-9999999LL if the Big Bang occurred at time -9999999 (see zic.c)
+#  -DHAVE_DIRECT_H if mkdir needs <direct.h> (MS-Windows)
 #  -DHAVE_DOS_FILE_NAMES if file names have drive specifiers etc. (MS-DOS)
 #  -DHAVE_GETTEXT=1 if 'gettext' works (GNU, Linux, Solaris); also see LDLIBS
 #  -DHAVE_INCOMPATIBLE_CTIME_R=1 if your system's time.h declares
@@ -116,6 +117,8 @@ LDLIBS=
 #  -DHAVE_LOCALTIME_RZ=0 if you do not want zdump to use localtime_rz
 #	This defaults to 1 if a working localtime_rz seems to be available.
 #	localtime_rz can make zdump significantly faster, but is nonstandard.
+#  -DHAVE_POSIX_DECLS=0 if your system's include files do not declare
+#	functions like 'link' or variables like 'tzname' required by POSIX
 #  -DHAVE_STDINT_H=1 if you have a pre-C99 compiler with "stdint.h"
 #  -DHAVE_STRFTIME_L=1 if <time.h> declares locale_t and strftime_l
 #	This defaults to 0 if _POSIX_VERSION < 200809, 1 otherwise.
diff --git a/date.c b/date.c
index 824e57d..4c11f61 100644
--- a/date.c
+++ b/date.c
@@ -42,10 +42,12 @@
 #define SECSPERMIN	60
 #endif /* !defined SECSPERMIN */
 
+#if !HAVE_POSIX_DECLS
 extern char **		environ;
 extern char *		optarg;
 extern int		optind;
-extern char *		tzname[2];
+extern char *		tzname[];
+#endif
 
 static int		retval = EXIT_SUCCESS;
 
diff --git a/private.h b/private.h
index 1c176e6..6080e71 100644
--- a/private.h
+++ b/private.h
@@ -34,6 +34,10 @@
 #define HAVE_LINK		1
 #endif /* !defined HAVE_LINK */
 
+#ifndef HAVE_POSIX_DECLS
+#define HAVE_POSIX_DECLS 1
+#endif
+
 #ifndef HAVE_STRDUP
 #define HAVE_STRDUP 1
 #endif
@@ -106,6 +110,9 @@
 #ifndef ENAMETOOLONG
 # define ENAMETOOLONG EINVAL
 #endif
+#ifndef ENOTSUP
+# define ENOTSUP EINVAL
+#endif
 #ifndef EOVERFLOW
 # define EOVERFLOW EINVAL
 #endif
@@ -379,6 +386,8 @@ time_t time(time_t *);
 void tzset(void);
 #endif
 
+#if !HAVE_POSIX_DECLS
+
 /*
 ** Some time.h implementations don't declare asctime_r.
 ** Others might define it as a macro.
@@ -402,6 +411,8 @@ extern int daylight;
 extern long altzone;
 #endif
 
+#endif
+
 /*
 ** The STD_INSPIRED functions are similar, but most also need
 ** declarations if time_tz is defined.
diff --git a/strftime.c b/strftime.c
index 7a139bd..f75f9fd 100644
--- a/strftime.c
+++ b/strftime.c
@@ -106,7 +106,9 @@ static char *	_fmt(const char *, const struct tm *, char *, const char *,
 			int *);
 static char *	_yconv(int, int, bool, bool, char *, char const *);
 
+#if !HAVE_POSIX_DECLS
 extern char *	tzname[];
+#endif
 
 #ifndef YEAR_2000_NAME
 #define YEAR_2000_NAME	"CHECK_STRFTIME_FORMATS_FOR_TWO_DIGIT_YEARS"
diff --git a/zdump.c b/zdump.c
index 063a263..64d90f6 100644
--- a/zdump.c
+++ b/zdump.c
@@ -238,12 +238,14 @@ enum { SECSPER400YEARS_FITS = SECSPERLYEAR <= INTMAX_MAX / 400 };
 # define timezone_t char **
 #endif
 
+#if !HAVE_POSIX_DECLS
 extern char **	environ;
 extern int	getopt(int argc, char * const argv[],
 			const char * options);
 extern char *	optarg;
 extern int	optind;
-extern char *	tzname[2];
+extern char *	tzname[];
+#endif
 
 /* The minimum and maximum finite time values.  */
 enum { atime_shift = CHAR_BIT * sizeof (time_t) - 2 };
diff --git a/zic.c b/zic.c
index 78ab870..0ec3359 100644
--- a/zic.c
+++ b/zic.c
@@ -22,6 +22,13 @@ typedef int_fast64_t	zic_t;
 #define ZIC_MAX_ABBR_LEN_WO_WARN	6
 #endif /* !defined ZIC_MAX_ABBR_LEN_WO_WARN */
 
+#ifdef HAVE_DIRECT_H
+# include <direct.h>
+# include <io.h>
+# undef mkdir
+# define mkdir(name, mode) _mkdir(name)
+#endif
+
 #if HAVE_SYS_STAT_H
 #include <sys/stat.h>
 #endif
@@ -87,17 +94,19 @@ struct zone {
 	zic_t		z_untiltime;
 };
 
+#if !HAVE_POSIX_DECLS
 extern int	getopt(int argc, char * const argv[],
 			const char * options);
 extern int	link(const char * fromname, const char * toname);
 extern char *	optarg;
 extern int	optind;
+#endif
 
 #if ! HAVE_LINK
-# define link(from, to) (-1)
+# define link(from, to) (errno = ENOTSUP, -1)
 #endif
 #if ! HAVE_SYMLINK
-# define symlink(from, to) (-1)
+# define symlink(from, to) (errno = ENOTSUP, -1)
 #endif
 
 static void	addtt(zic_t starttime, int type);
@@ -758,41 +767,47 @@ dolink(char const *fromfield, char const *tofield)
 			progname, fromname, e);
 		exit(EXIT_FAILURE);
 	}
-	if (itsdir(toname) <= 0)
-		remove(toname);
 	if (link(fromname, toname) != 0) {
-		int	result;
+	  int link_errno = errno;
+	  bool retry_if_link_supported = false;
 
-		if (! mkdirs(toname))
-			exit(EXIT_FAILURE);
-
-		result = link(fromname, toname);
-		if (result != 0) {
-				const char *s = fromfield;
-				const char *t;
-				char *p;
-				size_t dotdots = 0;
-				register char * symlinkcontents = NULL;
-
-				do
-					 t = s;
-				while ((s = strchr(s, '/'))
-				       && ! strncmp (fromfield, tofield,
-						     ++s - fromfield));
-
-				for (s = tofield + (t - fromfield); *s; s++)
-				  dotdots += *s == '/';
-				symlinkcontents
-				  = emalloc(3 * dotdots + strlen(t) + 1);
-				for (p = symlinkcontents; dotdots-- != 0; p += 3)
-				  memcpy(p, "../", 3);
-				strcpy(p, t);
-				result = symlink(symlinkcontents, toname);
-				if (result == 0)
-warning(_("hard link failed, symbolic link used"));
-				free(symlinkcontents);
-		}
-		if (result != 0) {
+	  if (link_errno == ENOENT || link_errno == ENOTSUP) {
+	    if (! mkdirs(toname))
+	      exit(EXIT_FAILURE);
+	    retry_if_link_supported = true;
+	  }
+	  if ((link_errno == EEXIST || link_errno == ENOTSUP)
+	      && itsdir(toname) == 0
+	      && (remove(toname) == 0 || errno == ENOENT))
+	    retry_if_link_supported = true;
+	  if (retry_if_link_supported && link_errno != ENOTSUP)
+	    link_errno = link(fromname, toname) == 0 ? 0 : errno;
+	  if (link_errno != 0) {
+	    const char *s = fromfield;
+	    const char *t;
+	    char *p;
+	    size_t dotdots = 0;
+	    char *symlinkcontents;
+	    int symlink_result;
+
+	    do
+	      t = s;
+	    while ((s = strchr(s, '/'))
+		   && strncmp(fromfield, tofield, ++s - fromfield) == 0);
+
+	    for (s = tofield + (t - fromfield); *s; s++)
+	      dotdots += *s == '/';
+	    symlinkcontents = emalloc(3 * dotdots + strlen(t) + 1);
+	    for (p = symlinkcontents; dotdots-- != 0; p += 3)
+	      memcpy(p, "../", 3);
+	    strcpy(p, t);
+	    symlink_result = symlink(symlinkcontents, toname);
+	    free(symlinkcontents);
+	    if (symlink_result == 0) {
+	      if (link_errno != ENOTSUP)
+		warning(_("symbolic link used because hard link failed: %s"),
+			strerror (link_errno));
+	    } else {
 			FILE *fp, *tp;
 			int c;
 			fp = fopen(fromname, "rb");
@@ -815,8 +830,11 @@ warning(_("hard link failed, symbolic link used"));
 				putc(c, tp);
 			close_file(fp, fromname);
 			close_file(tp, toname);
-			warning(_("link failed, copy used"));
-		}
+			if (link_errno != ENOTSUP)
+			  warning(_("copy used because hard link failed: %s"),
+				  strerror (link_errno));
+	    }
+	  }
 	}
 	free(fromname);
 	free(toname);
@@ -863,18 +881,17 @@ itsdir(char const *name)
 {
 	struct stat st;
 	int res = stat(name, &st);
-	if (res != 0)
-		return res;
 #ifdef S_ISDIR
-	return S_ISDIR(st.st_mode) != 0;
-#else
-	{
+	if (res == 0)
+		return S_ISDIR(st.st_mode) != 0;
+#endif
+	if (res == 0 || errno == EOVERFLOW) {
 		char *nameslashdot = relname(name, ".");
-		res = stat(nameslashdot, &st);
+		bool dir = stat(nameslashdot, &st) == 0 || errno == EOVERFLOW;
 		free(nameslashdot);
-		return res == 0;
+		return dir;
 	}
-#endif
+	return -1;
 }
 
 /*
@@ -1685,7 +1702,7 @@ writezone(const char *const name, const char *const string, char version)
 	/*
 	** Remove old file, if any, to snap links.
 	*/
-	if (itsdir(fullname) <= 0 && remove(fullname) != 0 && errno != ENOENT) {
+	if (itsdir(fullname) == 0 && remove(fullname) != 0 && errno != ENOENT) {
 		const char *e = strerror(errno);
 
 		fprintf(stderr, _("%s: Can't remove %s: %s\n"),
openSUSE Build Service is sponsored by