[tz] compiling tzcode with mingw gcc compiler

Paul Eggert eggert at cs.ucla.edu
Thu Sep 26 00:51:46 UTC 2013


Thanks for the heads-up.  I pushed the following somewhat-different
patch; I think it should fix the problem, though I don't have easy
access to MinGW and I haven't tested it.  If you run into further
problems please let the list know.

>From d884cda073ddd1f795b1d8f0d8968cc4ecac65f1 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert at cs.ucla.edu>
Date: Wed, 25 Sep 2013 17:49:49 -0700
Subject: [PATCH] build: port to MinGW and fix symlink bugs

MinGW problem reported by Theo Veenker in
<http://mm.icann.org/pipermail/tz/2013-September/020378.html>.
The patched code should work even on POSIXish hosts
where 'link' and 'symlink' fail for whatever reason,
e.g., if the destination file system is VFAT.
Also, the patch fixes some bugs when symlinks are used.
* Makefile (CFLAGS): Mention HAVE_LINK in the comment.
(TZDSRCS): Add asctime.o, since MinGW lacks asctime.
(TZDOBJS): Add asctime.c.
* private.h (HAVE_LINK): Default to 1.
* zic.c (link) [!HAVE_LINK]: New macro.
(symlink) [!HAVE_SYMLINK]: New macro.
(dolink): Fix some bugs when 'link' fails but 'symlink' succeeds.
Fall back on copying when both fail.
* NEWS: Document the above.

Release tzcode2013f and tzdata2013f.
* NEWS, Makefile (VERSION): Increase to 2013f.
---
 Makefile  |  5 +++--
 NEWS      |  6 +++++
 private.h |  4 ++++
 zic.c     | 75 +++++++++++++++++++++++++++++++++++++++++++++++----------------
 4 files changed, 69 insertions(+), 21 deletions(-)

diff --git a/Makefile b/Makefile
index efce751..b37fc74 100644
--- a/Makefile
+++ b/Makefile
@@ -107,6 +107,7 @@ LDLIBS=
 #  -DHAVE_INCOMPATIBLE_CTIME_R=1 if your system's time.h declares
 #	ctime_r and asctime_r incompatibly with the POSIX standard (Solaris 8).
 #  -DHAVE_INTTYPES_H=1 if you have a pre-C99 compiler with "inttypes.h"
+#  -DHAVE_LINK=0 if your system lacks a link function
 #  -DHAVE_SETTIMEOFDAY=0 if settimeofday does not exist (SVR0?)
 #  -DHAVE_SETTIMEOFDAY=1 if settimeofday has just 1 arg (SVR4)
 #  -DHAVE_SETTIMEOFDAY=2 if settimeofday uses 2nd arg (4.3BSD)
@@ -299,8 +300,8 @@ CC=		$(cc) -DTZDIR=\"$(TZDIR)\"
 
 TZCSRCS=	zic.c localtime.c asctime.c scheck.c ialloc.c
 TZCOBJS=	zic.o localtime.o asctime.o scheck.o ialloc.o
-TZDSRCS=	zdump.c localtime.c ialloc.c
-TZDOBJS=	zdump.o localtime.o ialloc.o
+TZDSRCS=	zdump.c localtime.c ialloc.c asctime.o
+TZDOBJS=	zdump.o localtime.o ialloc.o asctime.c
 DATESRCS=	date.c localtime.c strftime.c asctime.c
 DATEOBJS=	date.o localtime.o strftime.o asctime.o
 LIBSRCS=	localtime.c asctime.c difftime.c
diff --git a/NEWS b/NEWS
index 6324d25..14f75fa 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,12 @@ News for the tz database
 
 Unreleased, experimental changes
 
+  Changes affecting 'zic'
+
+    'zic' now runs on platforms that lack both hard links and symlinks.
+    (Thanks to Theo Veenker for reporting the problem, for MinGW.)
+    Also, fix some bugs on platforms that lack hard links but have symlinks.
+
   Changes affecting the build procedure
 
     The 'leapseconds' file is again put into the tzdata tarball.
diff --git a/private.h b/private.h
index 3a19305..c85ebaa 100644
--- a/private.h
+++ b/private.h
@@ -34,6 +34,10 @@
 #define HAVE_INCOMPATIBLE_CTIME_R	0
 #endif /* !defined INCOMPATIBLE_CTIME_R */
 
+#ifndef HAVE_LINK
+#define HAVE_LINK		1
+#endif /* !defined HAVE_SYMLINK */
+
 #ifndef HAVE_SETTIMEOFDAY
 #define HAVE_SETTIMEOFDAY	3
 #endif /* !defined HAVE_SETTIMEOFDAY */
diff --git a/zic.c b/zic.c
index 7e231b5..dcf51e2 100644
--- a/zic.c
+++ b/zic.c
@@ -107,6 +107,13 @@ extern int	link(const char * fromname, const char * toname);
 extern char *	optarg;
 extern int	optind;
 
+#if ! HAVE_LINK
+# define link(from, to) (-1)
+#endif
+#if ! HAVE_SYMLINK
+# define symlink(from, to) (-1)
+#endif
+
 static void	addtt(zic_t starttime, int type);
 static int	addtype(zic_t gmtoff, const char * abbr, int isdst,
 				int ttisstd, int ttisgmt);
@@ -612,41 +619,71 @@ dolink(const char *const fromfield, const char *const tofield)
 	*/
 	if (!itsdir(toname))
 		(void) remove(toname);
-	if (link(fromname, toname) != 0) {
+	if (link(fromname, toname) != 0
+	    && access(fromname, F_OK) == 0 && !itsdir(fromname)) {
 		int	result;
 
 		if (mkdirs(toname) != 0)
 			exit(EXIT_FAILURE);
 
 		result = link(fromname, toname);
-#if HAVE_SYMLINK
-		if (result != 0 &&
-			access(fromname, F_OK) == 0 &&
-			!itsdir(fromname)) {
-				const char *s = tofield;
+		if (result != 0) {
+				const char *s = fromfield;
+				const char *t;
 				register char * symlinkcontents = NULL;
 
-				while ((s = strchr(s+1, '/')) != NULL)
+				do
+					 t = s;
+				while ((s = strchr(s, '/'))
+				       && ! strncmp (fromfield, tofield,
+						     ++s - fromfield));
+
+				for (s = tofield + (t - fromfield);
+				     (s = strchr(s, '/'));
+				     s++)
 					symlinkcontents =
 						ecatalloc(symlinkcontents,
 						"../");
-				symlinkcontents =
-					ecatalloc(symlinkcontents,
-					fromname);
-				result = symlink(symlinkcontents,
-					toname);
+				symlinkcontents = ecatalloc(symlinkcontents, t);
+				result = symlink(symlinkcontents, toname);
 				if (result == 0)
 warning(_("hard link failed, symbolic link used"));
 				free(symlinkcontents);
 		}
-#endif /* HAVE_SYMLINK */
 		if (result != 0) {
-			const char *e = strerror(errno);
-
-			(void) fprintf(stderr,
-				_("%s: Can't link from %s to %s: %s\n"),
-				progname, fromname, toname, e);
-			exit(EXIT_FAILURE);
+			FILE *fp, *tp;
+			int c;
+			fp = fopen(fromname, "rb");
+			if (!fp) {
+				const char *e = strerror(errno);
+				(void) fprintf(stderr,
+					       _("%s: Can't read %s: %s\n"),
+					       progname, fromname, e);
+				exit(EXIT_FAILURE);
+			}
+			tp = fopen(toname, "wb");
+			if (!tp) {
+				const char *e = strerror(errno);
+				(void) fprintf(stderr,
+					       _("%s: Can't create %s: %s\n"),
+					       progname, toname, e);
+				exit(EXIT_FAILURE);
+			}
+			while ((c = getc(fp)) != EOF)
+				putc(c, tp);
+			if (ferror(fp) || fclose(fp)) {
+				(void) fprintf(stderr,
+					       _("%s: Error reading %s\n"),
+					       progname, fromname);
+				exit(EXIT_FAILURE);
+			}
+			if (ferror(tp) || fclose(tp)) {
+				(void) fprintf(stderr,
+					       _("%s: Error writing %s\n"),
+					       progname, toname);
+				exit(EXIT_FAILURE);
+			}
+			warning(_("link failed, copy used"));
 		}
 	}
 	free(fromname);
-- 
1.8.1.2



More information about the tz mailing list