glibc install problem caused by bug in zic (fwd)

Feb. 25, 2002
1:55 a.m.
Hi, I had sent this mail originally to the glibc people, but Ulrich Drepper <drepper@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@mppmu.mpg.de> ---------- Forwarded message ---------- Date: Fri, 15 Feb 2002 12:01:27 +0100 From: peb@mppmu.mpg.de To: glibc-bug-reports-stable@gnu.org Subject: glibc install problem caused by bug in zic >Submitter-Id: net >Originator: Peter Breitenlohner <peb@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@mppmu.mpg.de>
8521
Age (days ago)
8521
Last active (days ago)
0 comments
1 participants
participants (1)
-
Peter Breitenlohner