FW: glibc install problem caused by bug in zic (fwd)

Olson, Arthur David (NCI) olsona at dc37a.nci.nih.gov
Mon Feb 25 14:09:37 UTC 2002


Peter Breitenlohner is not on the time zone mailing list; direct replies
appropriately.

				--ado

-----Original Message-----
From: Peter Breitenlohner [mailto:peb at mppmu.mpg.de]
Sent: Monday, February 25, 2002 4:56 AM
To: tz at elsie.nci.nih.gov
Subject: glibc install problem caused by bug in zic (fwd)


Hi,

I had sent this mail originally to the glibc people, but Ulrich Drepper
<drepper at redhat.com> told me to resend it to you, since he "doesn't want to
get involved in a discussion about the details".

Peter Breitenlohner <peb at mppmu.mpg.de>

---------- Forwarded message ----------
Date: Fri, 15 Feb 2002 12:01:27 +0100
From: peb at mppmu.mpg.de
To: glibc-bug-reports-stable at gnu.org
Subject: glibc install problem caused by bug in zic

>Submitter-Id:	net
>Originator:
  Peter Breitenlohner <peb at mppmu.mpg.de>
>Organization:
  Max-Planck-Institute for Physics, Munich, Germany
>
>Confidential:	no
>Synopsis:	due to a bug in zic, a bad symlink was installed
>Severity:	non-critical
>Priority:	low
>Category:	libc
>Class:		sw-bug
>Release:	libc-2.2.5
>Environment:

Host type: i586-pc-linux-gnu
System: Linux pcl321 2.2.18 #2 Mon May 28 16:46:54 CEST 2001 i686 unknown
Architecture: i686

Addons: linuxthreads
Build CFLAGS: -O2
Build CC: gcc
Compiler version: 2.95.3 20010315 (release)
Kernel headers: 2.2.18
Symbol versioning: yes
Build static: yes
Build shared: yes
Build pic-default: no
Build profile: yes
Build omitfp: no
Build bounded: no
Build static-nss: no
Stdio: libio

>Description:
	I had uncommented the "PARALLELMFLAGS = -j 4" in the toplevel
Makefile
	and did first "make" and then "make install_root=/ROOT install"
	During the install I got the message
	"systemv", line 44: warning: hard link failed, symbolic link used
	and the result was a bad symlink
	/ROOT/usr/share/zoneinfo/right/SystemV/AST4 ->
		..//ROOT/usr/share/zoneinfo/right/America/Puerto_Rico
	As far as I can see two things came together:
	(A)
	Bad timing between two instances of zic, where one tried to link to
	a file which the other had not yet created.
	Things could actually have been much worse:
	If an old but corrupt file `right/America/Puerto_Rico' would
	have already existed, zic would have created a hard link to that old
	file before the other instance of zic had recreated a good new
version
	of it and no one would have noticed.
	(B)
	A bug in zic when creating a link but fromfile doesn't exist. The
	logic to build a relative path for symlink is just plain wrong.
>How-To-Repeat:
	(A)
	Obviously difficult
	(B)
	Run "zic -d `pwd`/zone test" with an input file `test'
	containing just one line: "Link Some/Where Bad/Link"
>Fix:
	(A)
	It may be difficult to fix this reliably, on the other hand an
	occasional (correct) symlink might be unpleasant but certainly does
	no harm.
	One way out would be to move the link from the file `systemv' to the
	file `northamerica' where the `America/Puerto_Rico' zone is defined
	(and the same for all other links), but you probably find this
	undesirable.
	Or you could disable the parallel-make while installing in the
	`timezone' directory.
	BTW: Can a similar problem occur in other directories?
	Or (less reliably) one could change the behaviour of zic:
	if the first attempt to create a (hard) link fails, wait for a short
	period and try again. I assume zic ist primarily (or even only)
	used when installing glibc, so this shouldn't harm anyone.
	(B)
	This patch corrects the way zic constructs the path for symlink:
==================================================================
diff -ur glibc-2.2.5.orig/timezone/zic.c glibc-2.2.5/timezone/zic.c
--- glibc-2.2.5.orig/timezone/zic.c	Wed Dec  5 19:53:04 2001
+++ glibc-2.2.5/timezone/zic.c	Fri Feb 15 11:03:20 2002
@@ -622,26 +622,45 @@
 		result = link(fromname, toname);
 #if (HAVE_SYMLINK - 0)
 		if (result != 0) {
-		        const char *s = tofile;
-		        register char *symlinkcontents = NULL;
-		        while ((s = strchr(s+1, '/')) != NULL)
-			        symlinkcontents = ecatalloc(symlinkcontents,
"../");
-			symlinkcontents = ecatalloc(symlinkcontents,
fromname);
+			char *f = fromname;
+			char *t = toname;
+		        char *s = NULL;
+		        /*
+		        ** First skip over common path prefix
+		        */
+		        while ((t[0] != '\0') && (t[0] == f[0])) {
+		        	if (t[0] == '/')
+		        		s = t;
+				t++;
+				f++;
+		        }
+		        /*
+		        ** Proceed if there is a common prefix,
+		        ** otherwise we can't create a reasonable symlink
+		        ** (only happens when input and -d option are weird)
+		        */
+		        if (s != NULL) {
+			        register char *symlinkcontents = NULL;
+			        f = fromname+(s-toname);
+			        while ((s = strchr(s+1, '/')) != NULL)
+				        symlinkcontents =
ecatalloc(symlinkcontents, "../");
+				symlinkcontents = ecatalloc(symlinkcontents,
f+1);

-			result = unlink(toname);
-			if (result != 0 && errno != ENOENT) {
-				const char *e = strerror(errno);
+				result = unlink(toname);
+				if (result != 0 && errno != ENOENT) {
+					const char *e = strerror(errno);

-				(void) fprintf(stderr,
-					       _("%s: Can't unlink  %s:
%s\n"),
-					       progname, toname, e);
-				(void) exit(EXIT_FAILURE);
-			}
+					(void) fprintf(stderr,
+						       _("%s: Can't unlink
%s: %s\n"),
+						       progname, toname, e);
+					(void) exit(EXIT_FAILURE);
+				}

-			result = symlink(symlinkcontents, toname);
-			if (result == 0)
-warning(_("hard link failed, symbolic link used"));
-			ifree(symlinkcontents);
+				result = symlink(symlinkcontents, toname);
+				if (result == 0)
+					warning(_("hard link failed,
symbolic link used"));
+				ifree(symlinkcontents);
+			}
 		}
 #endif
 		if (result != 0) {
==================================================================

regards
Peter Breitenlohner <peb at mppmu.mpg.de>



More information about the tz mailing list