Dear maintainers of the tzcode, I noticed I could't build the tzcode from Mingw gcc. Therefore I'd like to suggest some additions/changes. They are fairly trivial, see below. Theo Veenker Main change required is the addition of a (conditional) link() function into zic.c as this function is not provided on a Windows platform. private.h: Add: #ifndef HAVE_LINK #define HAVE_LINK 1 #endif /* !defined HAVE_LINK */ zic.c: Add: #if !HAVE_LINK #define SCRATCH_SIZE 8000 int link(const char * fromname, const char * toname) { FILE * fi; FILE * fo; char * scratch; int err = 0; fi = fopen(fromname, "rb"); if (!fi) return -1; fo = fopen(toname, "wb"); if (!fo) { fclose(fi); return -1; } scratch = (char*)emalloc(SCRATCH_SIZE); while (!feof(fi)) { int nread = fread(scratch, 1, SCRATCH_SIZE, fi); if (nread > 0) { int nwritten = fwrite(scratch, 1, nread, fo); if (nwritten != nread) { err = -1; break; } } else if (feof(fi)) { break; } else if (ferror(fi)) { err = -1; break; } } free(scratch); fclose(fo); fclose(fi); return err; } #endif /* !HAVE_LINK */ Makefile: Linking zdump requires asctime.c and asctime.o to be added to symbols TZDSRCS resp. TZDOBJS: TZDSRCS= zdump.c localtime.c asctime.c ialloc.c TZDOBJS= zdump.o localtime.o asctime.o ialloc.o Also add comment: # -DHAVE_LINK=0 if your system lacks the link function To test compilation using i686-w64-mingw32-gcc under Linux: make CFLAGS="-DHAVE_STDINT_H -DSTD_INSPIRED -DHAVE_SYS_WAIT_H=0 -DHAVE_SYS_STAT_H=0 -DHAVE_UNISTD_H=0 -DHAVE_SYMLINK=0 -DHAVE_LINK=0" cc=i686-w64-mingw32-gcc To test compilation using Mingw gcc under Windows: make CFLAGS="-DHAVE_STDINT_H -DSTD_INSPIRED -DHAVE_SYS_WAIT_H=0 -DHAVE_SYS_STAT_H=0 -DHAVE_UNISTD_H=0 -DHAVE_SYMLINK=0 -DHAVE_LINK=0" cc=gcc -- Theo Veenker | Beexy - Behavioral Experiment Software +31(0)524-541531 | +31(0)6-42525777 mobile theo.veenker@beexy.nl | www.beexy.nl
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@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
participants (2)
-
Paul Eggert -
Theo Veenker