RFC: ldconfig speedup

Jakub Jelinek jakub@redhat.com
Fri Jul 27 12:20:00 GMT 2007


On Tue, Jul 03, 2007 at 01:45:13PM -0700, Ulrich Drepper wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> Andreas Jaeger wrote:
> > What do you think now?
> 
> Lot's of formatting and little style/semantic problems all over the place.

...

I haven't seen any progress with this, so in order to speed up the process
I tried to address all issues Uli and Jim raised plus several minor or
less minor things.

Attached is a new patch, plus interdiff from the last patch Andreas posted.
I have briefly tested it, but nothing extensive.

The remaining issues I'd like to discuss before changing them are:

1) ldconfig uses the /var/cache/ldconfig/aux-cache cache only to speed up
   mapping of the cache_entry_id -> { flags, osversion, soname }
   so what's the point of aux_cache_file_entry containing value (aka path)
   or hwcap?
2) the aux_entries linked list will usually contain roughly 2000+ entries,
   isn't that above the count where using a simple hash table or rb tree
   (hsearch_r is probably a bad idea, as it needs strings as keys,
   but we could either implement our own trivial hash table
   (say hashing with nextprime (aux_cache->nlibs) hash table
   entries with chains), or could grab from libiberty Vlad's hashtab.c
   (that's probably overkill, we know how many entries we have, no need
   to ever resize it), or use tsearch).
3) couldn't the aux-cache entries also contain negative lookups?
   E.g. we have *.so linker scripts in the directories, that can be
   cached as cache_entry_id -> { -1, -1, 0 } or something similar
   to denote non-DSO.

	Jakub
-------------- next part --------------
--- libc/elf/readlib.c.jj	2007-07-16 09:58:46.000000000 +0200
+++ libc/elf/readlib.c	2007-07-27 12:23:15.000000000 +0200
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999-2003, 2005 Free Software Foundation, Inc.
+/* Copyright (C) 1999-2003, 2005, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Andreas Jaeger <aj@suse.de>, 1999 and
 		  Jakub Jelinek <jakub@redhat.com>, 1999.
@@ -69,7 +69,7 @@ static struct known_names known_libs[] =
 int
 process_file (const char *real_file_name, const char *file_name,
 	      const char *lib, int *flag, unsigned int *osversion,
-	      char **soname, int is_link)
+	      char **soname, int is_link, int *has_soname)
 {
   FILE *file;
   struct stat64 statbuf;
@@ -78,6 +78,9 @@ process_file (const char *real_file_name
   ElfW(Ehdr) *elf_header;
   struct exec *aout_header;
 
+  if (has_soname)
+    *has_soname = 0;
+
   ret = 0;
   *flag = FLAG_ANY;
   *soname = NULL;
@@ -135,7 +138,7 @@ process_file (const char *real_file_name
       )
     {
       /* Aout files don't have a soname, just return the name
-         including the major number.  */
+	 including the major number.  */
       char *copy, *major, *dot;
       copy = xstrdup (lib);
       major = strstr (copy, ".so.");
@@ -166,9 +169,16 @@ process_file (const char *real_file_name
   /* Libraries have to be shared object files.  */
   else if (elf_header->e_type != ET_DYN)
     ret = 1;
-  else if (process_elf_file (file_name, lib, flag, osversion, soname,
+  else
+    {
+      if (process_elf_file (file_name, lib, flag, osversion, soname,
 			     file_contents, statbuf.st_size))
-    ret = 1;
+	ret = 1;
+      else if (*soname == NULL)
+	*soname = xstrdup (lib);
+      else if (has_soname)
+	*has_soname = 1;
+    }
 
  done:
   /* Clean up allocated memory and resources.  */
--- libc/elf/ldconfig.c.jj	2007-07-16 09:58:46.000000000 +0200
+++ libc/elf/ldconfig.c	2007-07-27 12:36:15.000000000 +0200
@@ -112,6 +112,9 @@ static char *opt_chroot;
 /* Manually link given shared libraries.  */
 static int opt_manual_link;
 
+/* Should we ignore an old auxiliary cache file?  */
+static int opt_ignore_aux_cache;
+
 /* Cache file to use.  */
 static char *cache_file;
 
@@ -142,6 +145,7 @@ static const struct argp_option options[
   { NULL, 'n', NULL, 0, N_("Only process directories specified on the command line.  Don't build cache."), 0},
   { NULL, 'l', NULL, 0, N_("Manually link individual libraries."), 0},
   { "format", 'c', N_("FORMAT"), 0, N_("Format to use: new, old or compat (default)"), 0},
+  { "ignore-aux-cache", 'i', NULL, 0, N_("Ignore auxiliary cache file"), 0},
   { NULL, 0, NULL, 0, NULL, 0 }
 };
 
@@ -238,10 +242,15 @@ parse_opt (int key, char *arg, struct ar
     {
     case 'C':
       cache_file = arg;
+      /* Ignore auxiliary cache since we use non-standard cache.  */
+      opt_ignore_aux_cache = 1;
       break;
     case 'f':
       config_file = arg;
       break;
+    case 'i':
+      opt_ignore_aux_cache = 1;
+      break;
     case 'l':
       opt_manual_link = 1;
       break;
@@ -518,7 +527,7 @@ manual_link (char *library)
   if (libname)
     {
       /* Successfully split names.  Check if path is just "/" to avoid
-         an empty path.  */
+	 an empty path.  */
       if (libname == path)
 	{
 	  libname = library + 1;
@@ -573,7 +582,7 @@ manual_link (char *library)
       return;
     }
   if (process_file (real_library, library, libname, &flag, &osversion,
-		    &soname, 0))
+		    &soname, 0, NULL))
     {
       error (0, 0, _("No link created since soname could not be found for %s"),
 	     library);
@@ -618,6 +627,7 @@ struct dlib_entry
   int flag;
   int is_link;
   unsigned int osversion;
+  struct stat64 stat_buf;
   struct dlib_entry *next;
 };
 
@@ -625,23 +635,7 @@ struct dlib_entry
 static void
 search_dir (const struct dir_entry *entry)
 {
-  DIR *dir;
-  struct dirent64 *direntry;
-  char *file_name, *dir_name, *real_file_name, *real_name;
-  int file_name_len, real_file_name_len, len;
-  char *soname;
-  struct dlib_entry *dlibs;
-  struct dlib_entry *dlib_ptr;
-  struct stat64 lstat_buf, stat_buf;
-  int is_link, is_dir;
   uint64_t hwcap = path_hwcap (entry->path);
-  unsigned int osversion;
-
-  file_name_len = PATH_MAX;
-  file_name = alloca (file_name_len);
-
-  dlibs = NULL;
-
   if (opt_verbose)
     {
       if (hwcap != 0)
@@ -650,6 +644,11 @@ search_dir (const struct dir_entry *entr
 	printf ("%s:\n", entry->path);
     }
 
+  char *dir_name;
+  char *real_file_name;
+  size_t real_file_name_len;
+  size_t file_name_len = PATH_MAX;
+  char *file_name = alloca (file_name_len);
   if (opt_chroot)
     {
       dir_name = chroot_canon (opt_chroot, entry->path);
@@ -663,6 +662,7 @@ search_dir (const struct dir_entry *entr
       real_file_name = file_name;
     }
 
+  DIR *dir;
   if (dir_name == NULL || (dir = opendir (dir_name)) == NULL)
     {
       if (opt_verbose)
@@ -672,6 +672,8 @@ search_dir (const struct dir_entry *entr
       return;
     }
 
+  struct dirent64 *direntry;
+  struct dlib_entry *dlibs = NULL;
   while ((direntry = readdir64 (dir)) != NULL)
     {
       int flag;
@@ -695,7 +697,8 @@ search_dir (const struct dir_entry *entr
 #endif
 	      !is_hwcap_platform (direntry->d_name)))
 	continue;
-      len = strlen (direntry->d_name);
+
+      size_t len = strlen (direntry->d_name);
       /* Skip temporary files created by the prelink program.  Files with
 	 names like these are never really DSOs we want to look at.  */
       if (len >= sizeof (".#prelink#") - 1)
@@ -727,7 +730,10 @@ search_dir (const struct dir_entry *entr
 	    }
 	  sprintf (real_file_name, "%s/%s", dir_name, direntry->d_name);
 	}
+
+      struct stat64 lstat_buf;
 #ifdef _DIRENT_HAVE_D_TYPE
+      /* We optimize and try to do the lstat call only if needed.  */
       if (direntry->d_type != DT_UNKNOWN)
 	lstat_buf.st_mode = DTTOIF (direntry->d_type);
       else
@@ -738,9 +744,11 @@ search_dir (const struct dir_entry *entr
 	    continue;
 	  }
 
-      is_link = S_ISLNK (lstat_buf.st_mode);
+      struct stat64 stat_buf;
+      int is_dir;
+      int is_link = S_ISLNK (lstat_buf.st_mode);
       if (is_link)
-        {
+	{
 	  /* In case of symlink, we check if the symlink refers to
 	     a directory. */
 	  if (__builtin_expect (stat64 (real_file_name, &stat_buf), 0))
@@ -754,6 +762,12 @@ search_dir (const struct dir_entry *entr
 	      continue;
 	    }
 	  is_dir = S_ISDIR (stat_buf.st_mode);
+
+	  /* lstat_buf is later stored, update contents.  */
+	  lstat_buf.st_dev = stat_buf.st_dev;
+	  lstat_buf.st_ino = stat_buf.st_ino;
+	  lstat_buf.st_size = stat_buf.st_size;
+	  lstat_buf.st_ctime = stat_buf.st_ctime;
 	}
       else
 	is_dir = S_ISDIR (lstat_buf.st_mode);
@@ -767,36 +781,28 @@ search_dir (const struct dir_entry *entr
 	  new_entry->path = xstrdup (file_name);
 	  new_entry->flag = entry->flag;
 	  new_entry->next = NULL;
-	  if (is_link)
+#ifdef _DIRENT_HAVE_D_TYPE
+	  /* We have filled in lstat only #ifndef
+	     _DIRENT_HAVE_D_TYPE.  Fill it in if needed.  */
+	  if (!is_link
+	      && direntry->d_type != DT_UNKNOWN
+	      && __builtin_expect (lstat64 (real_file_name, &lstat_buf), 0))
 	    {
-	      new_entry->ino = stat_buf.st_ino;
-	      new_entry->dev = stat_buf.st_dev;
+	      error (0, errno, _("Cannot lstat %s"), file_name);
+	      free (new_entry->path);
+	      free (new_entry);
+	      continue;
 	    }
-	  else
-	    {
-#ifdef _DIRENT_HAVE_D_TYPE
-	      /* We have filled in lstat only #ifndef
-		 _DIRENT_HAVE_D_TYPE.  Fill it in if needed.  */
-	      if (direntry->d_type != DT_UNKNOWN
-		  && __builtin_expect (lstat64 (real_file_name, &lstat_buf),
-				       0))
-		{
-		  error (0, errno, _("Cannot lstat %s"), file_name);
-		  free (new_entry->path);
-		  free (new_entry);
-		  continue;
-		}
 #endif
-
-	      new_entry->ino = lstat_buf.st_ino;
-	      new_entry->dev = lstat_buf.st_dev;
-	    }
+	  new_entry->ino = lstat_buf.st_ino;
+	  new_entry->dev = lstat_buf.st_dev;
 	  add_single_dir (new_entry, 0);
 	  continue;
 	}
       else if (!S_ISREG (lstat_buf.st_mode) && !is_link)
 	continue;
 
+      char *real_name;
       if (opt_chroot && is_link)
 	{
 	  real_name = chroot_canon (opt_chroot, file_name);
@@ -810,14 +816,34 @@ search_dir (const struct dir_entry *entr
       else
 	real_name = real_file_name;
 
-      if (process_file (real_name, file_name, direntry->d_name, &flag,
-			&osversion, &soname, is_link))
+#ifdef _DIRENT_HAVE_D_TYPE
+      /* Call lstat64 if not done yet.  */
+      if (!is_link
+	  && direntry->d_type != DT_UNKNOWN
+	  && __builtin_expect (lstat64 (real_file_name, &lstat_buf), 0))
 	{
-	  if (real_name != real_file_name)
-	    free (real_name);
+	  error (0, errno, _("Cannot lstat %s"), file_name);
 	  continue;
 	}
+#endif
+
+      /* has_soname stores whether library has unique soname.  */
+      int has_soname = 1;
 
+      /* First search whether the auxiliary cache contains this
+	 library already and it's not changed.  */
+      char *soname;
+      unsigned int osversion;
+      if (!search_aux_cache (&lstat_buf, &flag, &osversion, &soname))
+	{
+	  if (process_file (real_name, file_name, direntry->d_name, &flag,
+			    &osversion, &soname, is_link, &has_soname))
+	    {
+	      if (real_name != real_file_name)
+		free (real_name);
+	      continue;
+	    }
+	}
 
       /* A link may just point to itself.  */
       if (is_link)
@@ -834,13 +860,15 @@ search_dir (const struct dir_entry *entr
 		  || strncmp (real_base_name, soname, len) != 0)
 		is_link = 0;
 	    }
-        }
+	}
 
       if (real_name != real_file_name)
 	free (real_name);
 
       if (is_link)
 	{
+	  if (strcmp (soname, direntry->d_name) != 0)
+	    has_soname = 0;
 	  free (soname);
 	  soname = xstrdup (direntry->d_name);
 	}
@@ -848,7 +876,22 @@ search_dir (const struct dir_entry *entr
       if (flag == FLAG_ELF
 	  && (entry->flag == FLAG_ELF_LIBC5
 	      || entry->flag == FLAG_ELF_LIBC6))
-	flag = entry->flag;
+       {
+	 flag = entry->flag;
+	 /* Invalidate id data as we changed the flag.  */
+	 has_soname = 0;
+       }
+
+      if (!has_soname)
+       {
+	 /* The soname or flags depend on file name of dir properties,
+	     so invalidate id entry.  */
+	 lstat_buf.st_ino = 0;
+	 lstat_buf.st_ctime = 0;
+	 lstat_buf.st_size = 0;
+	 lstat_buf.st_dev = 0;
+       }
+
       /* Some sanity checks to print warnings.  */
       if (opt_verbose)
 	{
@@ -864,6 +907,7 @@ search_dir (const struct dir_entry *entr
 	}
 
       /* Add library to list.  */
+      struct dlib_entry *dlib_ptr;
       for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next)
 	{
 	  /* Is soname already in list?  */
@@ -887,13 +931,21 @@ search_dir (const struct dir_entry *entr
 			       && flag == FLAG_ELF)
 			dlib_ptr->flag = flag;
 		      else
-			error (0, 0, _("libraries %s and %s in directory %s have same soname but different type."),
-			       dlib_ptr->name, direntry->d_name, entry->path);
+			{
+			  error (0, 0, _("libraries %s and %s in directory %s have same soname but different type."),
+				 dlib_ptr->name, direntry->d_name,
+				 entry->path);
+			  lstat_buf.st_dev = 0;
+			  lstat_buf.st_ino = 0;
+			  lstat_buf.st_size = 0;
+			  lstat_buf.st_ctime = 0;
+			}
 		    }
 		  free (dlib_ptr->name);
-		  dlib_ptr->osversion = osversion;
 		  dlib_ptr->name = xstrdup (direntry->d_name);
 		  dlib_ptr->is_link = is_link;
+		  dlib_ptr->osversion = osversion;
+		  dlib_ptr->stat_buf = lstat_buf;
 		}
 	      /* Don't add this library, abort loop.  */
 	      /* Also free soname, since it's dynamically allocated.  */
@@ -906,10 +958,11 @@ search_dir (const struct dir_entry *entr
 	{
 	  dlib_ptr = (struct dlib_entry *)xmalloc (sizeof (struct dlib_entry));
 	  dlib_ptr->name = xstrdup (direntry->d_name);
-	  dlib_ptr->flag = flag;
-	  dlib_ptr->osversion = osversion;
 	  dlib_ptr->soname = soname;
+	  dlib_ptr->flag = flag;
 	  dlib_ptr->is_link = is_link;
+	  dlib_ptr->osversion = osversion;
+	  dlib_ptr->stat_buf = lstat_buf;
 	  /* Add at head of list.  */
 	  dlib_ptr->next = dlibs;
 	  dlibs = dlib_ptr;
@@ -920,6 +973,7 @@ search_dir (const struct dir_entry *entr
 
   /* Now dlibs contains a list of all libs - add those to the cache
      and created all symbolic links.  */
+  struct dlib_entry *dlib_ptr;
   for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next)
     {
       /* Don't create links to links.  */
@@ -928,7 +982,7 @@ search_dir (const struct dir_entry *entr
 		      dlib_ptr->soname);
       if (opt_build_cache)
 	add_to_cache (entry->path, dlib_ptr->soname, dlib_ptr->flag,
-		      dlib_ptr->osversion, hwcap);
+		      dlib_ptr->osversion, hwcap, &dlib_ptr->stat_buf);
     }
 
   /* Free all resources.  */
@@ -1246,7 +1300,7 @@ main (int argc, char **argv)
   if (opt_chroot)
     {
       /* Canonicalize the directory name of cache_file, not cache_file,
-         because we'll rename a temporary cache file to it.  */
+	 because we'll rename a temporary cache file to it.  */
       char *p = strrchr (cache_file, '/');
       char *canon = chroot_canon (opt_chroot,
 				  p ? (*p = '\0', cache_file) : "/");
@@ -1293,10 +1347,15 @@ main (int argc, char **argv)
 	add_system_dir (LIBDIR);
     }
 
+  if (! opt_ignore_aux_cache)
+    load_aux_cache (cache_file, _PATH_LDCONFIG_AUX_CACHE);
+
   search_dirs ();
 
+  free_aux_cache ();
+
   if (opt_build_cache)
-    save_cache (cache_file);
+    save_cache (cache_file, _PATH_LDCONFIG_AUX_CACHE);
 
   return 0;
 }
--- libc/elf/cache.c.jj	2007-07-16 09:58:46.000000000 +0200
+++ libc/elf/cache.c	2007-07-27 13:06:39.000000000 +0200
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999-2003,2005,2006 Free Software Foundation, Inc.
+/* Copyright (C) 1999-2003,2005,2006,2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Andreas Jaeger <aj@suse.de>, 1999.
 
@@ -20,6 +20,7 @@
 #include <error.h>
 #include <dirent.h>
 #include <inttypes.h>
+#include <libgen.h>
 #include <libintl.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -33,6 +34,14 @@
 #include <ldconfig.h>
 #include <dl-cache.h>
 
+struct cache_entry_id
+{
+  uint64_t ino;
+  uint64_t ctime;
+  uint64_t size;
+  uint64_t dev;
+};
+
 struct cache_entry
 {
   char *lib;			/* Library name.  */
@@ -41,12 +50,44 @@ struct cache_entry
   unsigned int osversion;	/* Required OS version.  */
   uint64_t hwcap;		/* Important hardware capabilities.  */
   int bits_hwcap;		/* Number of bits set in hwcap.  */
+  struct cache_entry_id id;	/* Unique id of entry.  */
   struct cache_entry *next;	/* Next entry in list.  */
 };
 
+
+#define AUX_CACHEMAGIC		"glibc-ld.so.auxcache-1.0"
+
+struct aux_cache_file_entry
+{
+  int32_t flags;		/* This is 1 for an ELF library.  */
+  uint32_t key;			/* String table indices.  */
+  uint32_t value;
+  uint32_t osversion;		/* Required OS version.	 */
+  uint64_t hwcap;		/* Hwcap entry.	 */
+  struct cache_entry_id id;	/* Unique id of entry.  */
+};
+
+/* ldconfig maintains an auxiliary cache file that allows
+   only reading those libraries that have changed since the last iteration.
+   For this for each library some information is cached in the auxiliary
+   cache.  */
+struct aux_cache_file
+{
+  char magic[sizeof AUX_CACHEMAGIC - 1];
+  uint32_t nlibs;		/* Number of entries.  */
+  uint32_t len_strings;		/* Size of string table. */
+  struct cache_entry_id idldsocache; /* Info about ld.so.cache  .*/
+  struct aux_cache_file_entry libs[0]; /* Entries describing libraries.  */
+  /* After this the string table of size len_strings is found.	*/
+};
+
+
 /* List of all cache entries.  */
 static struct cache_entry *entries;
 
+/* List of all entries in auxiliary cache for incremental mode.  */
+static struct cache_entry *aux_entries;
+
 static const char *flag_descr[] =
 { "libc4", "ELF", "libc5", "libc6"};
 
@@ -80,16 +121,16 @@ print_entry (const char *lib, int flag, 
       fputs (",x86-64", stdout);
       break;
     case FLAG_S390_LIB64:
-      fputs(",64bit", stdout);
+      fputs (",64bit", stdout);
       break;
     case FLAG_POWERPC_LIB64:
-      fputs(",64bit", stdout);
+      fputs (",64bit", stdout);
       break;
     case FLAG_MIPS64_LIBN32:
-      fputs(",N32", stdout);
+      fputs (",N32", stdout);
       break;
     case FLAG_MIPS64_LIBN64:
-      fputs(",64bit", stdout);
+      fputs (",64bit", stdout);
     case 0:
       break;
     default:
@@ -128,19 +169,11 @@ print_entry (const char *lib, int flag, 
 void
 print_cache (const char *cache_name)
 {
-  size_t cache_size;
-  struct stat64 st;
-  int fd;
-  unsigned int i;
-  struct cache_file *cache;
-  struct cache_file_new *cache_new = NULL;
-  const char *cache_data;
-  int format = 0;
-
-  fd = open (cache_name, O_RDONLY);
+  int fd = open (cache_name, O_RDONLY);
   if (fd < 0)
     error (EXIT_FAILURE, errno, _("Can't open cache file %s\n"), cache_name);
 
+  struct stat64 st;
   if (fstat64 (fd, &st) < 0
       /* No need to map the file if it is empty.  */
       || st.st_size == 0)
@@ -149,14 +182,19 @@ print_cache (const char *cache_name)
       return;
     }
 
-  cache = mmap (0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
+  struct cache_file *cache
+    = mmap (NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
   if (cache == MAP_FAILED)
     error (EXIT_FAILURE, errno, _("mmap of cache file failed.\n"));
-  cache_size = st.st_size;
 
+  size_t cache_size = st.st_size;
   if (cache_size < sizeof (struct cache_file))
     error (EXIT_FAILURE, 0, _("File is not a cache file.\n"));
 
+  struct cache_file_new *cache_new = NULL;
+  const char *cache_data;
+  int format = 0;
+
   if (memcmp (cache->magic, CACHEMAGIC, sizeof CACHEMAGIC - 1))
     {
       /* This can only be the new format without the old one.  */
@@ -201,7 +239,7 @@ print_cache (const char *cache_name)
       printf (_("%d libs found in cache `%s'\n"), cache->nlibs, cache_name);
 
       /* Print everything.  */
-      for (i = 0; i < cache->nlibs; i++)
+      for (unsigned int i = 0; i < cache->nlibs; i++)
 	print_entry (cache_data + cache->libs[i].key,
 		     cache->libs[i].flags, 0, 0,
 		     cache_data + cache->libs[i].value);
@@ -212,7 +250,7 @@ print_cache (const char *cache_name)
 	      cache_new->nlibs, cache_name);
 
       /* Print everything.  */
-      for (i = 0; i < cache_new->nlibs; i++)
+      for (unsigned int i = 0; i < cache_new->nlibs; i++)
 	print_entry (cache_data + cache_new->libs[i].key,
 		     cache_new->libs[i].flags,
 		     cache_new->libs[i].osversion,
@@ -231,15 +269,11 @@ init_cache (void)
   entries = NULL;
 }
 
-
-
-static
-int compare (const struct cache_entry *e1, const struct cache_entry *e2)
+static int
+compare (const struct cache_entry *e1, const struct cache_entry *e2)
 {
-  int res;
-
   /* We need to swap entries here to get the correct sort order.  */
-  res = _dl_cache_libcmp (e2->lib, e1->lib);
+  int res = _dl_cache_libcmp (e2->lib, e1->lib);
   if (res == 0)
     {
       if (e1->flags < e2->flags)
@@ -265,31 +299,21 @@ int compare (const struct cache_entry *e
 
 /* Save the contents of the cache.  */
 void
-save_cache (const char *cache_name)
+save_cache (const char *cache_name, const char *aux_cache_name)
 {
-  struct cache_entry *entry;
-  int fd, idx_old, idx_new;
-  size_t total_strlen, len;
-  char *strings, *str, *temp_name;
-  struct cache_file *file_entries = NULL;
-  struct cache_file_new *file_entries_new = NULL;
-  size_t file_entries_size = 0;
-  size_t file_entries_new_size = 0;
-  unsigned int str_offset;
-  /* Number of cache entries.  */
-  int cache_entry_count = 0;
-  /* Number of normal cache entries.  */
-  int cache_entry_old_count = 0;
-  /* Pad for alignment of cache_file_new.  */
-  size_t pad;
-
   /* The cache entries are sorted already, save them in this order. */
 
   /* Count the length of all strings.  */
   /* The old format doesn't contain hwcap entries and doesn't contain
      libraries in subdirectories with hwcaps entries.  Count therefore
      also all entries with hwcap == 0.  */
-  total_strlen = 0;
+  size_t total_strlen = 0;
+  struct cache_entry *entry;
+  /* Number of cache entries.  */
+  int cache_entry_count = 0;
+  /* Number of normal cache entries.  */
+  int cache_entry_old_count = 0;
+
   for (entry = entries; entry != NULL; entry = entry->next)
     {
       /* Account the final NULs.  */
@@ -300,8 +324,8 @@ save_cache (const char *cache_name)
     }
 
   /* Create the on disk cache structure.  */
-  /* First an array for all strings.  */
-  strings = (char *)xmalloc (total_strlen);
+  struct cache_file *file_entries = NULL;
+  size_t file_entries_size = 0;
 
   if (opt_format != 2)
     {
@@ -315,25 +339,27 @@ save_cache (const char *cache_name)
       /* And the list of all entries in the old format.  */
       file_entries_size = sizeof (struct cache_file)
 	+ cache_entry_old_count * sizeof (struct file_entry);
-      file_entries = (struct cache_file *) xmalloc (file_entries_size);
+      file_entries = xmalloc (file_entries_size);
 
       /* Fill in the header.  */
-      memset (file_entries, 0, sizeof (struct cache_file));
+      memset (file_entries, '\0', sizeof (struct cache_file));
       memcpy (file_entries->magic, CACHEMAGIC, sizeof CACHEMAGIC - 1);
 
       file_entries->nlibs = cache_entry_old_count;
     }
 
+  struct cache_file_new *file_entries_new = NULL;
+  size_t file_entries_new_size = 0;
+
   if (opt_format != 0)
     {
       /* And the list of all entries in the new format.  */
       file_entries_new_size = sizeof (struct cache_file_new)
 	+ cache_entry_count * sizeof (struct file_entry_new);
-      file_entries_new =
-	(struct cache_file_new *) xmalloc (file_entries_new_size);
+      file_entries_new = xmalloc (file_entries_new_size);
 
       /* Fill in the header.  */
-      memset (file_entries_new, 0, sizeof (struct cache_file_new));
+      memset (file_entries_new, '\0', sizeof (struct cache_file_new));
       memcpy (file_entries_new->magic, CACHEMAGIC_NEW,
 	      sizeof CACHEMAGIC_NEW - 1);
       memcpy (file_entries_new->version, CACHE_VERSION,
@@ -343,17 +369,41 @@ save_cache (const char *cache_name)
       file_entries_new->len_strings = total_strlen;
     }
 
-  pad = ALIGN_CACHE (file_entries_size) - file_entries_size;
+  /* Auxiliary cache.  */
+  size_t aux_file_entries_size
+    = sizeof (struct aux_cache_file)
+      + cache_entry_count * sizeof (struct aux_cache_file_entry);
+  struct aux_cache_file *aux_file_entries = xmalloc (aux_file_entries_size);
+
+  /* Fill in the header of the auxiliary cache.  */
+  memset (aux_file_entries, '\0', sizeof (struct aux_cache_file));
+  memcpy (aux_file_entries->magic, AUX_CACHEMAGIC,
+	  sizeof AUX_CACHEMAGIC - 1);
+
+  aux_file_entries->nlibs = cache_entry_count;
+  aux_file_entries->len_strings = total_strlen;
+
+  /* Pad for alignment of cache_file_new.  */
+  size_t pad = ALIGN_CACHE (file_entries_size) - file_entries_size;
 
   /* If we have both formats, we hide the new format in the strings
      table, we have to adjust all string indices for this so that
      old libc5/glibc 2 dynamic linkers just ignore them.  */
+  unsigned int str_offset;
   if (opt_format != 0)
     str_offset = file_entries_new_size;
   else
     str_offset = 0;
 
-  str = strings;
+  /* Initial String offset for auxiliary cache is always 0.  */
+  unsigned int aux_str_offset = 0;
+
+  /* An array for all strings.  */
+  char *strings = xmalloc (total_strlen);
+  char *str = strings;
+  int idx_old;
+  int idx_new;
+
   for (idx_old = 0, idx_new = 0, entry = entries; entry != NULL;
        entry = entry->next, ++idx_new)
     {
@@ -375,21 +425,31 @@ save_cache (const char *cache_name)
 	  file_entries_new->libs[idx_new].hwcap = entry->hwcap;
 	  file_entries_new->libs[idx_new].key = str_offset;
 	}
-      len = strlen (entry->lib);
+
+      aux_file_entries->libs[idx_new].flags = entry->flags;
+      aux_file_entries->libs[idx_new].key = aux_str_offset;
+      aux_file_entries->libs[idx_new].osversion = entry->osversion;
+      aux_file_entries->libs[idx_new].hwcap = entry->hwcap;
+      aux_file_entries->libs[idx_new].id = entry->id;
+
+      size_t len = strlen (entry->lib);
       str = stpcpy (str, entry->lib);
       /* Account the final NUL.  */
       ++str;
       str_offset += len + 1;
+      aux_str_offset += len + 1;
       /* Then the path.  */
       if (opt_format != 2 && entry->hwcap == 0)
 	file_entries->libs[idx_old].value = str_offset + pad;
       if (opt_format != 0)
 	file_entries_new->libs[idx_new].value = str_offset;
+      aux_file_entries->libs[idx_new].value = aux_str_offset;
       len = strlen (entry->path);
       str = stpcpy (str, entry->path);
       /* Account the final NUL.  */
       ++str;
       str_offset += len + 1;
+      aux_str_offset += len + 1;
       /* Ignore entries with hwcap for old format.  */
       if (entry->hwcap == 0)
 	++idx_old;
@@ -403,16 +463,12 @@ save_cache (const char *cache_name)
   /* Write out the cache.  */
 
   /* Write cache first to a temporary file and rename it later.  */
-  temp_name = xmalloc (strlen (cache_name) + 2);
+  char *temp_name = xmalloc (strlen (cache_name) + 2);
   sprintf (temp_name, "%s~", cache_name);
-  /* First remove an old copy if it exists.  */
-  if (unlink (temp_name) && errno != ENOENT)
-    error (EXIT_FAILURE, errno, _("Can't remove old temporary cache file %s"),
-	   temp_name);
 
   /* Create file.  */
-  fd = open (temp_name, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW,
-	     S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR);
+  int fd = open (temp_name, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW,
+		 S_IRUSR|S_IWUSR);
   if (fd < 0)
     error (EXIT_FAILURE, errno, _("Can't create temporary cache file %s"),
 	   temp_name);
@@ -439,32 +495,76 @@ save_cache (const char *cache_name)
 	error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
     }
 
-  if (write (fd, strings, total_strlen) != (ssize_t) total_strlen)
+  if (write (fd, strings, total_strlen) != (ssize_t) total_strlen
+      || close (fd))
     error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
 
-  close (fd);
-
   /* Make sure user can always read cache file */
   if (chmod (temp_name, S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR))
     error (EXIT_FAILURE, errno,
 	   _("Changing access rights of %s to %#o failed"), temp_name,
-	   S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR);
+	   S_IRGRP|S_IRUSR|S_IWUSR);
 
   /* Move temporary to its final location.  */
   if (rename (temp_name, cache_name))
     error (EXIT_FAILURE, errno, _("Renaming of %s to %s failed"), temp_name,
 	   cache_name);
 
+  struct stat64 st;
+  if (stat64 (cache_name, &st) < 0)
+    error (EXIT_FAILURE, errno, _("stat of cache file %s failed.\n"),
+	   cache_name);
+
+  aux_file_entries->idldsocache.ino = (uint64_t) st.st_ino;
+  aux_file_entries->idldsocache.ctime = (uint64_t) st.st_ctime;
+  aux_file_entries->idldsocache.size = (uint64_t) st.st_size;
+  aux_file_entries->idldsocache.dev = (uint64_t) st.st_dev;
+
+  /* Write out auxiliary cache file.  */
+  /* Write auxiliary cache first to a temporary file and rename it later.  */
+
+  temp_name = xmalloc (strlen (aux_cache_name) + 2);
+  sprintf (temp_name, "%s~", aux_cache_name);
+
+  /* Check that directory exists and create if needed.  */
+  char *dir = strdupa (aux_cache_name);
+  dir = dirname (dir);
+  if (stat64 (dir, &st) < 0)
+    {
+      if (mkdir (dir, 0700) < 0)
+	error (EXIT_FAILURE, errno, _("Cannot create directory %s"), dir);
+    }
+
+  /* Create file.  */
+  fd = open (temp_name, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW, S_IRUSR|S_IWUSR);
+  if (fd < 0)
+    error (EXIT_FAILURE, errno,
+	   _("Can't create temporary auxiliary cache file %s"),
+	   temp_name);
+
+  if (write (fd, aux_file_entries, aux_file_entries_size)
+	  != (ssize_t) aux_file_entries_size)
+	error (EXIT_FAILURE, errno,
+	       _("Writing of auxiliary cache data failed"));
+
+  if (write (fd, strings, total_strlen) != (ssize_t) total_strlen
+      || close (fd))
+    error (EXIT_FAILURE, errno, _("Writing of auxiliary cache data failed"));
+
+  /* Move temporary to its final location.  */
+  if (rename (temp_name, aux_cache_name))
+    error (EXIT_FAILURE, errno, _("Renaming of %s to %s failed"), temp_name,
+	   aux_cache_name);
+
   /* Free all allocated memory.  */
   free (file_entries_new);
   free (file_entries);
+  free (aux_file_entries);
   free (strings);
 
   while (entries)
     {
       entry = entries;
-      free (entry->path);
-      free (entry->lib);
       entries = entries->next;
       free (entry);
     }
@@ -474,35 +574,36 @@ save_cache (const char *cache_name)
 /* Add one library to the cache.  */
 void
 add_to_cache (const char *path, const char *lib, int flags,
-	      unsigned int osversion, uint64_t hwcap)
+	      unsigned int osversion, uint64_t hwcap,
+	      struct stat64 *stat_buf)
 {
-  struct cache_entry *new_entry, *ptr, *prev;
-  char *full_path;
-  size_t len, i;
-
-  new_entry = (struct cache_entry *) xmalloc (sizeof (struct cache_entry));
-
-  len = strlen (lib) + strlen (path) + 2;
-
-  full_path = (char *) xmalloc (len);
-  snprintf (full_path, len, "%s/%s", path, lib);
-
-  new_entry->lib = xstrdup (lib);
-  new_entry->path = full_path;
+  size_t liblen = strlen (lib) + 1;
+  size_t len = liblen + strlen (path) + 1;
+  struct cache_entry *new_entry
+    = xmalloc (sizeof (struct cache_entry) + liblen + len);
+
+  new_entry->lib = memcpy ((char *) (new_entry + 1), lib, liblen);
+  new_entry->path = new_entry->lib + liblen;
+  snprintf (new_entry->path, len, "%s/%s", path, lib);
   new_entry->flags = flags;
   new_entry->osversion = osversion;
   new_entry->hwcap = hwcap;
   new_entry->bits_hwcap = 0;
+  new_entry->id.ino = (uint64_t) stat_buf->st_ino;
+  new_entry->id.ctime = (uint64_t) stat_buf->st_ctime;
+  new_entry->id.size = (uint64_t) stat_buf->st_size;
+  new_entry->id.dev = (uint64_t) stat_buf->st_dev;
 
   /* Count the number of bits set in the masked value.  */
-  for (i = 0; (~((1ULL << i) - 1) & hwcap) != 0 && i < 8 * sizeof (hwcap); ++i)
+  for (size_t i = 0;
+       (~((1ULL << i) - 1) & hwcap) != 0 && i < 8 * sizeof (hwcap); ++i)
     if ((hwcap & (1ULL << i)) != 0)
       ++new_entry->bits_hwcap;
 
 
   /* Keep the list sorted - search for right place to insert.  */
-  ptr = entries;
-  prev = entries;
+  struct cache_entry *ptr = entries;
+  struct cache_entry *prev = entries;
   while (ptr != NULL)
     {
       if (compare (ptr, new_entry) > 0)
@@ -522,3 +623,122 @@ add_to_cache (const char *path, const ch
       prev->next = new_entry;
     }
 }
+
+/* Load auxiliary cache to search for unchanged entries.   */
+void
+load_aux_cache (const char *cache_name, const char *aux_cache_name)
+{
+  int fd = open (aux_cache_name, O_RDONLY);
+  if (fd < 0)
+    return;
+
+  struct stat64 st;
+  if (fstat64 (fd, &st) < 0 || st.st_size < sizeof (struct aux_cache_file))
+    {
+      close (fd);
+      return;
+    }
+
+  size_t aux_cache_size = st.st_size;
+  struct aux_cache_file *aux_cache
+    = mmap (NULL, aux_cache_size, PROT_READ, MAP_PRIVATE, fd, 0);
+  if (aux_cache == MAP_FAILED
+      || aux_cache_size < sizeof (struct aux_cache_file)
+      || memcmp (aux_cache->magic, AUX_CACHEMAGIC, sizeof AUX_CACHEMAGIC - 1)
+      || aux_cache->nlibs < 0
+      || aux_cache->nlibs >= aux_cache_size)
+    {
+      close (fd);
+      return;
+    }
+
+  /* Check that ld.so.cache has not been changed externally.  */
+  if (stat64 (cache_name, &st) < 0
+      || aux_cache->idldsocache.ino != (uint64_t) st.st_ino
+      || aux_cache->idldsocache.ctime != (uint64_t) st.st_ctime
+      || aux_cache->idldsocache.size != (uint64_t) st.st_size
+      || aux_cache->idldsocache.dev != (uint64_t) st.st_dev)
+    {
+      close (fd);
+      return;
+    }
+
+  const char *aux_cache_data
+    = (const char *) &aux_cache->libs[aux_cache->nlibs];
+
+  for (unsigned int i = 0; i < aux_cache->nlibs; i++)
+    {
+      size_t keylen = strlen (aux_cache_data + aux_cache->libs[i].key) + 1;
+      size_t vallen = strlen (aux_cache_data + aux_cache->libs[i].value) + 1;
+      struct cache_entry *new_entry
+	= xmalloc (sizeof (struct cache_entry) + keylen + vallen);
+
+      new_entry->lib = memcpy ((char *) (new_entry + 1),
+			       aux_cache_data + aux_cache->libs[i].key,
+			       keylen);
+      new_entry->path = memcpy (new_entry->lib + keylen,
+				aux_cache_data + aux_cache->libs[i].value,
+				vallen);
+      new_entry->flags = aux_cache->libs[i].flags;
+      new_entry->osversion = aux_cache->libs[i].osversion;
+
+      uint64_t hwcap = aux_cache->libs[i].hwcap;
+      new_entry->hwcap = hwcap;
+      new_entry->bits_hwcap = 0;
+      memcpy (&new_entry->id, &aux_cache->libs[i].id,
+	      sizeof (struct cache_entry_id));
+
+      /* Count the number of bits set in the masked value.  */
+      for (size_t j = 0;
+	   (~((1ULL << j) - 1) & hwcap) != 0 && j < 8 * sizeof (hwcap);
+	   ++j)
+	if ((hwcap & (1ULL << j)) != 0)
+	  ++new_entry->bits_hwcap;
+
+      new_entry->next = aux_entries;
+      aux_entries = new_entry;
+    }
+
+  munmap (aux_cache, aux_cache_size);
+  close (fd);
+}
+
+int
+search_aux_cache (struct stat64 *stat_buf, int *flags,
+		  unsigned int *osversion, char **soname)
+{
+  struct cache_entry *entry;
+  struct cache_entry_id id;
+
+  id.ino = (uint64_t) stat_buf->st_ino;
+  id.ctime = (uint64_t) stat_buf->st_ctime;
+  id.size = (uint64_t) stat_buf->st_size;
+  id.dev = (uint64_t) stat_buf->st_dev;
+  for (entry = aux_entries; entry; entry = entry->next)
+    {
+      if (id.ino == entry->id.ino
+	  && id.ctime == entry->id.ctime
+	  && id.size == entry->id.size
+	  && id.dev == entry->id.dev)
+	{
+	  *flags = entry->flags;
+	  *osversion = entry->osversion;
+	  *soname = xstrdup (entry->lib);
+	  return 1;
+	}
+    }
+  return 0;
+}
+
+void
+free_aux_cache (void)
+{
+  struct cache_entry *entry;
+
+  while (aux_entries)
+    {
+      entry = aux_entries;
+      aux_entries = entry->next;
+      free (entry);
+    }
+}
--- libc/sysdeps/generic/ldconfig.h.jj	2003-03-14 06:32:49.000000000 +0100
+++ libc/sysdeps/generic/ldconfig.h	2007-07-27 12:20:28.000000000 +0200
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 1999, 2000, 2002, 2003, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Andreas Jaeger <aj@suse.de>, 1999.
 
@@ -35,20 +35,31 @@
 #define FLAG_MIPS64_LIBN32	0x0600
 #define FLAG_MIPS64_LIBN64	0x0700
 
+/* Name of auxiliary cache.  */
+#define _PATH_LDCONFIG_AUX_CACHE "/var/cache/ldconfig/aux-cache"
+
 /* Declared in cache.c.  */
 extern void print_cache (const char *cache_name);
 
 extern void init_cache (void);
 
-extern void save_cache (const char *cache_name);
+extern void save_cache (const char *cache_name, const char *aux_cache_name);
 
 extern void add_to_cache (const char *path, const char *lib, int flags,
-			  unsigned int osversion, uint64_t hwcap);
+			  unsigned int osversion, uint64_t hwcap,
+			  struct stat64 *stat_buf);
+
+extern void load_aux_cache (const char *cache_name, const char *aux_cache_name);
+
+extern int search_aux_cache (struct stat64 *stat_buf, int *flags,
+			     unsigned int *osversion, char **soname);
+
+extern void free_aux_cache (void);
 
 /* Declared in readlib.c.  */
 extern int process_file (const char *real_file_name, const char *file_name,
 			 const char *lib, int *flag, unsigned int *osversion,
-			 char **soname, int is_link);
+			 char **soname, int is_link, int *has_soname);
 
 /* Declared in readelflib.c.  */
 extern int process_elf_file (const char *file_name, const char *lib, int *flag,
-------------- next part --------------
--- libc/elf/cache.c	3 Jul 2007 19:57:17 -0000
+++ libc/elf/cache.c	2007-07-27 13:06:39.000000000 +0200
@@ -20,6 +20,7 @@
 #include <error.h>
 #include <dirent.h>
 #include <inttypes.h>
+#include <libgen.h>
 #include <libintl.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -54,14 +55,13 @@
 };
 
 
-#define AUX_CACHEMAGIC		"glibc-ld.so.auxcache"
-#define AUX_CACHE_VERSION	"1.0"
-#define AUX_CACHEMAGIC_VERSION	AUX_CACHEMAGIC AUX_CACHE_VERSION
+#define AUX_CACHEMAGIC		"glibc-ld.so.auxcache-1.0"
 
 struct aux_cache_file_entry
 {
   int32_t flags;		/* This is 1 for an ELF library.  */
-  uint32_t key, value;		/* String table indices.  */
+  uint32_t key;			/* String table indices.  */
+  uint32_t value;
   uint32_t osversion;		/* Required OS version.	 */
   uint64_t hwcap;		/* Hwcap entry.	 */
   struct cache_entry_id id;	/* Unique id of entry.  */
@@ -74,7 +74,6 @@
 struct aux_cache_file
 {
   char magic[sizeof AUX_CACHEMAGIC - 1];
-  char version[sizeof AUX_CACHE_VERSION - 1];
   uint32_t nlibs;		/* Number of entries.  */
   uint32_t len_strings;		/* Size of string table. */
   struct cache_entry_id idldsocache; /* Info about ld.so.cache  .*/
@@ -122,16 +121,16 @@
       fputs (",x86-64", stdout);
       break;
     case FLAG_S390_LIB64:
-      fputs(",64bit", stdout);
+      fputs (",64bit", stdout);
       break;
     case FLAG_POWERPC_LIB64:
-      fputs(",64bit", stdout);
+      fputs (",64bit", stdout);
       break;
     case FLAG_MIPS64_LIBN32:
-      fputs(",N32", stdout);
+      fputs (",N32", stdout);
       break;
     case FLAG_MIPS64_LIBN64:
-      fputs(",64bit", stdout);
+      fputs (",64bit", stdout);
     case 0:
       break;
     default:
@@ -170,19 +169,11 @@
 void
 print_cache (const char *cache_name)
 {
-  size_t cache_size;
-  struct stat64 st;
-  int fd;
-  unsigned int i;
-  struct cache_file *cache;
-  struct cache_file_new *cache_new = NULL;
-  const char *cache_data;
-  int format = 0;
-
-  fd = open (cache_name, O_RDONLY);
+  int fd = open (cache_name, O_RDONLY);
   if (fd < 0)
     error (EXIT_FAILURE, errno, _("Can't open cache file %s\n"), cache_name);
 
+  struct stat64 st;
   if (fstat64 (fd, &st) < 0
       /* No need to map the file if it is empty.  */
       || st.st_size == 0)
@@ -191,14 +182,19 @@
       return;
     }
 
-  cache = mmap (0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
+  struct cache_file *cache
+    = mmap (NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
   if (cache == MAP_FAILED)
     error (EXIT_FAILURE, errno, _("mmap of cache file failed.\n"));
-  cache_size = st.st_size;
 
+  size_t cache_size = st.st_size;
   if (cache_size < sizeof (struct cache_file))
     error (EXIT_FAILURE, 0, _("File is not a cache file.\n"));
 
+  struct cache_file_new *cache_new = NULL;
+  const char *cache_data;
+  int format = 0;
+
   if (memcmp (cache->magic, CACHEMAGIC, sizeof CACHEMAGIC - 1))
     {
       /* This can only be the new format without the old one.  */
@@ -243,7 +239,7 @@
       printf (_("%d libs found in cache `%s'\n"), cache->nlibs, cache_name);
 
       /* Print everything.  */
-      for (i = 0; i < cache->nlibs; i++)
+      for (unsigned int i = 0; i < cache->nlibs; i++)
 	print_entry (cache_data + cache->libs[i].key,
 		     cache->libs[i].flags, 0, 0,
 		     cache_data + cache->libs[i].value);
@@ -254,7 +250,7 @@
 	      cache_new->nlibs, cache_name);
 
       /* Print everything.  */
-      for (i = 0; i < cache_new->nlibs; i++)
+      for (unsigned int i = 0; i < cache_new->nlibs; i++)
 	print_entry (cache_data + cache_new->libs[i].key,
 		     cache_new->libs[i].flags,
 		     cache_new->libs[i].osversion,
@@ -273,15 +269,11 @@
   entries = NULL;
 }
 
-
-
 static int
 compare (const struct cache_entry *e1, const struct cache_entry *e2)
 {
-  int res;
-
   /* We need to swap entries here to get the correct sort order.  */
-  res = _dl_cache_libcmp (e2->lib, e1->lib);
+  int res = _dl_cache_libcmp (e2->lib, e1->lib);
   if (res == 0)
     {
       if (e1->flags < e2->flags)
@@ -309,35 +301,19 @@
 void
 save_cache (const char *cache_name, const char *aux_cache_name)
 {
-  struct cache_entry *entry;
-  struct stat64 st;
-  int fd, idx_old, idx_new;
-  size_t total_strlen, len;
-  char *strings, *str, *temp_name;
-  struct cache_file *file_entries = NULL;
-  struct cache_file_new *file_entries_new = NULL;
-  struct aux_cache_file *aux_file_entries = NULL;
-  size_t file_entries_size = 0;
-  size_t file_entries_new_size = 0;
-  size_t aux_file_entries_size = 0;
-  unsigned int str_offset;
-  unsigned int aux_str_offset;
-  char *dir;
-
-  /* Number of cache entries.  */
-  int cache_entry_count = 0;
-  /* Number of normal cache entries.  */
-  int cache_entry_old_count = 0;
-  /* Pad for alignment of cache_file_new.  */
-  size_t pad;
-
   /* The cache entries are sorted already, save them in this order. */
 
   /* Count the length of all strings.  */
   /* The old format doesn't contain hwcap entries and doesn't contain
      libraries in subdirectories with hwcaps entries.  Count therefore
      also all entries with hwcap == 0.  */
-  total_strlen = 0;
+  size_t total_strlen = 0;
+  struct cache_entry *entry;
+  /* Number of cache entries.  */
+  int cache_entry_count = 0;
+  /* Number of normal cache entries.  */
+  int cache_entry_old_count = 0;
+
   for (entry = entries; entry != NULL; entry = entry->next)
     {
       /* Account the final NULs.  */
@@ -348,8 +324,8 @@
     }
 
   /* Create the on disk cache structure.  */
-  /* First an array for all strings.  */
-  strings = (char *)xmalloc (total_strlen);
+  struct cache_file *file_entries = NULL;
+  size_t file_entries_size = 0;
 
   if (opt_format != 2)
     {
@@ -363,25 +339,27 @@
       /* And the list of all entries in the old format.  */
       file_entries_size = sizeof (struct cache_file)
 	+ cache_entry_old_count * sizeof (struct file_entry);
-      file_entries = (struct cache_file *) xmalloc (file_entries_size);
+      file_entries = xmalloc (file_entries_size);
 
       /* Fill in the header.  */
-      memset (file_entries, 0, sizeof (struct cache_file));
+      memset (file_entries, '\0', sizeof (struct cache_file));
       memcpy (file_entries->magic, CACHEMAGIC, sizeof CACHEMAGIC - 1);
 
       file_entries->nlibs = cache_entry_old_count;
     }
 
+  struct cache_file_new *file_entries_new = NULL;
+  size_t file_entries_new_size = 0;
+
   if (opt_format != 0)
     {
       /* And the list of all entries in the new format.  */
       file_entries_new_size = sizeof (struct cache_file_new)
 	+ cache_entry_count * sizeof (struct file_entry_new);
-      file_entries_new =
-	(struct cache_file_new *) xmalloc (file_entries_new_size);
+      file_entries_new = xmalloc (file_entries_new_size);
 
       /* Fill in the header.  */
-      memset (file_entries_new, 0, sizeof (struct cache_file_new));
+      memset (file_entries_new, '\0', sizeof (struct cache_file_new));
       memcpy (file_entries_new->magic, CACHEMAGIC_NEW,
 	      sizeof CACHEMAGIC_NEW - 1);
       memcpy (file_entries_new->version, CACHE_VERSION,
@@ -392,34 +370,40 @@
     }
 
   /* Auxiliary cache.  */
-  aux_file_entries_size = sizeof (struct aux_cache_file)
-    + cache_entry_count * sizeof (struct aux_cache_file_entry);
-  aux_file_entries =
-	(struct aux_cache_file *) xmalloc (aux_file_entries_size);
+  size_t aux_file_entries_size
+    = sizeof (struct aux_cache_file)
+      + cache_entry_count * sizeof (struct aux_cache_file_entry);
+  struct aux_cache_file *aux_file_entries = xmalloc (aux_file_entries_size);
 
   /* Fill in the header of the auxiliary cache.  */
-  memset (aux_file_entries, 0, sizeof (struct aux_cache_file));
+  memset (aux_file_entries, '\0', sizeof (struct aux_cache_file));
   memcpy (aux_file_entries->magic, AUX_CACHEMAGIC,
 	  sizeof AUX_CACHEMAGIC - 1);
-  memcpy (aux_file_entries->version, AUX_CACHE_VERSION,
-	  sizeof AUX_CACHE_VERSION - 1);
 
   aux_file_entries->nlibs = cache_entry_count;
   aux_file_entries->len_strings = total_strlen;
 
-  pad = ALIGN_CACHE (file_entries_size) - file_entries_size;
+  /* Pad for alignment of cache_file_new.  */
+  size_t pad = ALIGN_CACHE (file_entries_size) - file_entries_size;
 
   /* If we have both formats, we hide the new format in the strings
      table, we have to adjust all string indices for this so that
      old libc5/glibc 2 dynamic linkers just ignore them.  */
+  unsigned int str_offset;
   if (opt_format != 0)
     str_offset = file_entries_new_size;
   else
     str_offset = 0;
+
   /* Initial String offset for auxiliary cache is always 0.  */
-  aux_str_offset = 0;
+  unsigned int aux_str_offset = 0;
+
+  /* An array for all strings.  */
+  char *strings = xmalloc (total_strlen);
+  char *str = strings;
+  int idx_old;
+  int idx_new;
 
-  str = strings;
   for (idx_old = 0, idx_new = 0, entry = entries; entry != NULL;
        entry = entry->next, ++idx_new)
     {
@@ -441,13 +425,14 @@
 	  file_entries_new->libs[idx_new].hwcap = entry->hwcap;
 	  file_entries_new->libs[idx_new].key = str_offset;
 	}
+
       aux_file_entries->libs[idx_new].flags = entry->flags;
+      aux_file_entries->libs[idx_new].key = aux_str_offset;
       aux_file_entries->libs[idx_new].osversion = entry->osversion;
       aux_file_entries->libs[idx_new].hwcap = entry->hwcap;
       aux_file_entries->libs[idx_new].id = entry->id;
-      aux_file_entries->libs[idx_new].key = aux_str_offset;
 
-      len = strlen (entry->lib);
+      size_t len = strlen (entry->lib);
       str = stpcpy (str, entry->lib);
       /* Account the final NUL.  */
       ++str;
@@ -478,16 +463,12 @@
   /* Write out the cache.  */
 
   /* Write cache first to a temporary file and rename it later.  */
-  temp_name = xmalloc (strlen (cache_name) + 2);
+  char *temp_name = xmalloc (strlen (cache_name) + 2);
   sprintf (temp_name, "%s~", cache_name);
-  /* First remove an old copy if it exists.  */
-  if (unlink (temp_name) && errno != ENOENT)
-    error (EXIT_FAILURE, errno, _("Can't remove old temporary cache file %s"),
-	   temp_name);
 
   /* Create file.  */
-  fd = open (temp_name, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW,
-	     S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR);
+  int fd = open (temp_name, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW,
+		 S_IRUSR|S_IWUSR);
   if (fd < 0)
     error (EXIT_FAILURE, errno, _("Can't create temporary cache file %s"),
 	   temp_name);
@@ -514,22 +495,22 @@
 	error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
     }
 
-  if (write (fd, strings, total_strlen) != (ssize_t) total_strlen)
+  if (write (fd, strings, total_strlen) != (ssize_t) total_strlen
+      || close (fd))
     error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
 
-  close (fd);
-
-  /* Make sure user can always read cache file.  */
+  /* Make sure user can always read cache file */
   if (chmod (temp_name, S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR))
     error (EXIT_FAILURE, errno,
 	   _("Changing access rights of %s to %#o failed"), temp_name,
-	   S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR);
+	   S_IRGRP|S_IRUSR|S_IWUSR);
 
   /* Move temporary to its final location.  */
   if (rename (temp_name, cache_name))
     error (EXIT_FAILURE, errno, _("Renaming of %s to %s failed"), temp_name,
 	   cache_name);
 
+  struct stat64 st;
   if (stat64 (cache_name, &st) < 0)
     error (EXIT_FAILURE, errno, _("stat of cache file %s failed.\n"),
 	   cache_name);
@@ -546,24 +527,16 @@
   sprintf (temp_name, "%s~", aux_cache_name);
 
   /* Check that directory exists and create if needed.  */
-  dir = xstrdup (aux_cache_name);
+  char *dir = strdupa (aux_cache_name);
   dir = dirname (dir);
   if (stat64 (dir, &st) < 0)
     {
-      if (mkdir (dir, 0750) < 0)
+      if (mkdir (dir, 0700) < 0)
 	error (EXIT_FAILURE, errno, _("Cannot create directory %s"), dir);
     }
-  free (dir);
-
-  /* First remove an old copy if it exists.  */
-  if (unlink (temp_name) && errno != ENOENT)
-    error (EXIT_FAILURE, errno,
-	   _("Can't remove old temporary auxiliary cache file %s"),
-	   temp_name);
 
   /* Create file.  */
-  fd = open (temp_name, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW,
-	     S_IRGRP|S_IRUSR|S_IWUSR);
+  fd = open (temp_name, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW, S_IRUSR|S_IWUSR);
   if (fd < 0)
     error (EXIT_FAILURE, errno,
 	   _("Can't create temporary auxiliary cache file %s"),
@@ -574,17 +547,10 @@
 	error (EXIT_FAILURE, errno,
 	       _("Writing of auxiliary cache data failed"));
 
-  if (write (fd, strings, total_strlen) != (ssize_t) total_strlen)
+  if (write (fd, strings, total_strlen) != (ssize_t) total_strlen
+      || close (fd))
     error (EXIT_FAILURE, errno, _("Writing of auxiliary cache data failed"));
 
-  close (fd);
-
-  /* Make sure user can always read auxiliary cache file.  */
-  if (chmod (temp_name, S_IRGRP|S_IRUSR|S_IWUSR))
-    error (EXIT_FAILURE, errno,
-	   _("Changing access rights of %s to %#o failed"), temp_name,
-	   S_IRGRP|S_IRUSR|S_IWUSR);
-
   /* Move temporary to its final location.  */
   if (rename (temp_name, aux_cache_name))
     error (EXIT_FAILURE, errno, _("Renaming of %s to %s failed"), temp_name,
@@ -599,8 +565,6 @@
   while (entries)
     {
       entry = entries;
-      free (entry->path);
-      free (entry->lib);
       entries = entries->next;
       free (entry);
     }
@@ -613,19 +577,14 @@
 	      unsigned int osversion, uint64_t hwcap,
 	      struct stat64 *stat_buf)
 {
-  struct cache_entry *new_entry, *ptr, *prev;
-  char *full_path;
-  size_t len, i;
-
-  new_entry = (struct cache_entry *) xmalloc (sizeof (struct cache_entry));
-
-  len = strlen (lib) + strlen (path) + 2;
-
-  full_path = (char *) xmalloc (len);
-  snprintf (full_path, len, "%s/%s", path, lib);
-
-  new_entry->lib = xstrdup (lib);
-  new_entry->path = full_path;
+  size_t liblen = strlen (lib) + 1;
+  size_t len = liblen + strlen (path) + 1;
+  struct cache_entry *new_entry
+    = xmalloc (sizeof (struct cache_entry) + liblen + len);
+
+  new_entry->lib = memcpy ((char *) (new_entry + 1), lib, liblen);
+  new_entry->path = new_entry->lib + liblen;
+  snprintf (new_entry->path, len, "%s/%s", path, lib);
   new_entry->flags = flags;
   new_entry->osversion = osversion;
   new_entry->hwcap = hwcap;
@@ -636,14 +595,15 @@
   new_entry->id.dev = (uint64_t) stat_buf->st_dev;
 
   /* Count the number of bits set in the masked value.  */
-  for (i = 0; (~((1ULL << i) - 1) & hwcap) != 0 && i < 8 * sizeof (hwcap); ++i)
+  for (size_t i = 0;
+       (~((1ULL << i) - 1) & hwcap) != 0 && i < 8 * sizeof (hwcap); ++i)
     if ((hwcap & (1ULL << i)) != 0)
       ++new_entry->bits_hwcap;
 
 
   /* Keep the list sorted - search for right place to insert.  */
-  ptr = entries;
-  prev = entries;
+  struct cache_entry *ptr = entries;
+  struct cache_entry *prev = entries;
   while (ptr != NULL)
     {
       if (compare (ptr, new_entry) > 0)
@@ -668,47 +628,25 @@
 void
 load_aux_cache (const char *cache_name, const char *aux_cache_name)
 {
-  size_t aux_cache_size;
-  const char *aux_cache_data;
-  struct stat64 st;
-  int fd;
-  unsigned int i;
-  size_t j;
-  struct aux_cache_file *aux_cache;
-  struct cache_entry *new_entry, *last;
-
-  uint64_t hwcap;
-
-  fd = open (aux_cache_name, O_RDONLY);
+  int fd = open (aux_cache_name, O_RDONLY);
   if (fd < 0)
     return;
 
-  if (fstat64 (fd, &st) < 0 || st.st_size == 0)
-    {
-      close (fd);
-      return;
-    }
-  aux_cache = mmap (0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
-  if (aux_cache == MAP_FAILED)
+  struct stat64 st;
+  if (fstat64 (fd, &st) < 0 || st.st_size < sizeof (struct aux_cache_file))
     {
       close (fd);
       return;
     }
 
-  aux_cache_size = st.st_size;
-  if (aux_cache_size < sizeof (struct aux_cache_file))
-    {
-      close (fd);
-      return;
-    }
-  if (memcmp (aux_cache->magic, AUX_CACHEMAGIC, sizeof AUX_CACHEMAGIC - 1)
-      || memcmp (aux_cache->version, AUX_CACHE_VERSION,
-		      sizeof AUX_CACHE_VERSION - 1))
-    {
-      close (fd);
-      return;
-    }
-  if (aux_cache->nlibs < 0 || aux_cache->nlibs >= aux_cache_size)
+  size_t aux_cache_size = st.st_size;
+  struct aux_cache_file *aux_cache
+    = mmap (NULL, aux_cache_size, PROT_READ, MAP_PRIVATE, fd, 0);
+  if (aux_cache == MAP_FAILED
+      || aux_cache_size < sizeof (struct aux_cache_file)
+      || memcmp (aux_cache->magic, AUX_CACHEMAGIC, sizeof AUX_CACHEMAGIC - 1)
+      || aux_cache->nlibs < 0
+      || aux_cache->nlibs >= aux_cache_size)
     {
       close (fd);
       return;
@@ -725,48 +663,48 @@
       return;
     }
 
-  aux_cache_data = (const char *) &aux_cache->libs[aux_cache->nlibs];
-  last = NULL;
-  for (i = 0; i < aux_cache->nlibs; i++)
-    {
-      new_entry = (struct cache_entry *)
-	xmalloc (sizeof (struct cache_entry));
-      new_entry->lib = xstrdup (aux_cache_data + aux_cache->libs[i].key);
-      new_entry->path = xstrdup (aux_cache_data + aux_cache->libs[i].value);
+  const char *aux_cache_data
+    = (const char *) &aux_cache->libs[aux_cache->nlibs];
+
+  for (unsigned int i = 0; i < aux_cache->nlibs; i++)
+    {
+      size_t keylen = strlen (aux_cache_data + aux_cache->libs[i].key) + 1;
+      size_t vallen = strlen (aux_cache_data + aux_cache->libs[i].value) + 1;
+      struct cache_entry *new_entry
+	= xmalloc (sizeof (struct cache_entry) + keylen + vallen);
+
+      new_entry->lib = memcpy ((char *) (new_entry + 1),
+			       aux_cache_data + aux_cache->libs[i].key,
+			       keylen);
+      new_entry->path = memcpy (new_entry->lib + keylen,
+				aux_cache_data + aux_cache->libs[i].value,
+				vallen);
       new_entry->flags = aux_cache->libs[i].flags;
       new_entry->osversion = aux_cache->libs[i].osversion;
-      hwcap = aux_cache->libs[i].hwcap;
+
+      uint64_t hwcap = aux_cache->libs[i].hwcap;
       new_entry->hwcap = hwcap;
       new_entry->bits_hwcap = 0;
-      memcpy(&new_entry->id, &aux_cache->libs[i].id,
-	     sizeof (struct cache_entry_id));
+      memcpy (&new_entry->id, &aux_cache->libs[i].id,
+	      sizeof (struct cache_entry_id));
 
       /* Count the number of bits set in the masked value.  */
-      for (j = 0;
+      for (size_t j = 0;
 	   (~((1ULL << j) - 1) & hwcap) != 0 && j < 8 * sizeof (hwcap);
 	   ++j)
 	if ((hwcap & (1ULL << j)) != 0)
 	  ++new_entry->bits_hwcap;
-      /* Add at the end of the list.  */
-      if (last == NULL)
-	last = new_entry;
-      else
-	{
-	  last->next = new_entry;
-	  last = new_entry;
-	}
+
       new_entry->next = aux_entries;
       aux_entries = new_entry;
     }
-  /* NULL terminate list.  */
-  if (last != NULL)
-    last->next = NULL;
+
   munmap (aux_cache, aux_cache_size);
   close (fd);
 }
 
 int
-search_aux_cache (const char *file, struct stat64 *stat_buf, int *flags,
+search_aux_cache (struct stat64 *stat_buf, int *flags,
 		  unsigned int *osversion, char **soname)
 {
   struct cache_entry *entry;
@@ -800,8 +738,6 @@
   while (aux_entries)
     {
       entry = aux_entries;
-      free (entry->path);
-      free (entry->lib);
       aux_entries = entry->next;
       free (entry);
     }
--- libc/elf/ldconfig.c	3 Jul 2007 19:57:18 -0000
+++ libc/elf/ldconfig.c	2007-07-27 12:36:15.000000000 +0200
@@ -635,23 +635,7 @@
 static void
 search_dir (const struct dir_entry *entry)
 {
-  DIR *dir;
-  struct dirent64 *direntry;
-  char *file_name, *dir_name, *real_file_name, *real_name;
-  int file_name_len, real_file_name_len, len;
-  char *soname;
-  struct dlib_entry *dlibs;
-  struct dlib_entry *dlib_ptr;
-  struct stat64 lstat_buf, stat_buf;
-  int is_link, is_dir, has_soname;
   uint64_t hwcap = path_hwcap (entry->path);
-  unsigned int osversion;
-
-  file_name_len = PATH_MAX;
-  file_name = alloca (file_name_len);
-
-  dlibs = NULL;
-
   if (opt_verbose)
     {
       if (hwcap != 0)
@@ -660,6 +644,11 @@
 	printf ("%s:\n", entry->path);
     }
 
+  char *dir_name;
+  char *real_file_name;
+  size_t real_file_name_len;
+  size_t file_name_len = PATH_MAX;
+  char *file_name = alloca (file_name_len);
   if (opt_chroot)
     {
       dir_name = chroot_canon (opt_chroot, entry->path);
@@ -673,6 +662,7 @@
       real_file_name = file_name;
     }
 
+  DIR *dir;
   if (dir_name == NULL || (dir = opendir (dir_name)) == NULL)
     {
       if (opt_verbose)
@@ -682,6 +672,8 @@
       return;
     }
 
+  struct dirent64 *direntry;
+  struct dlib_entry *dlibs = NULL;
   while ((direntry = readdir64 (dir)) != NULL)
     {
       int flag;
@@ -706,7 +698,7 @@
 	      !is_hwcap_platform (direntry->d_name)))
 	continue;
 
-      len = strlen (direntry->d_name);
+      size_t len = strlen (direntry->d_name);
       /* Skip temporary files created by the prelink program.  Files with
 	 names like these are never really DSOs we want to look at.  */
       if (len >= sizeof (".#prelink#") - 1)
@@ -738,6 +730,8 @@
 	    }
 	  sprintf (real_file_name, "%s/%s", dir_name, direntry->d_name);
 	}
+
+      struct stat64 lstat_buf;
 #ifdef _DIRENT_HAVE_D_TYPE
       /* We optimize and try to do the lstat call only if needed.  */
       if (direntry->d_type != DT_UNKNOWN)
@@ -750,7 +744,9 @@
 	    continue;
 	  }
 
-      is_link = S_ISLNK (lstat_buf.st_mode);
+      struct stat64 stat_buf;
+      int is_dir;
+      int is_link = S_ISLNK (lstat_buf.st_mode);
       if (is_link)
 	{
 	  /* In case of symlink, we check if the symlink refers to
@@ -766,13 +762,12 @@
 	      continue;
 	    }
 	  is_dir = S_ISDIR (stat_buf.st_mode);
-#ifndef _DIRENT_HAVE_D_TYPE
-	  /* lstat is later stored, update contents.  */
+
+	  /* lstat_buf is later stored, update contents.  */
+	  lstat_buf.st_dev = stat_buf.st_dev;
 	  lstat_buf.st_ino = stat_buf.st_ino;
-	  lstat_buf.st_ctime = stat_buf.st_ctime;
 	  lstat_buf.st_size = stat_buf.st_size;
-	  lstat_buf.st_dev = stat_buf.st_dev;
-#endif
+	  lstat_buf.st_ctime = stat_buf.st_ctime;
 	}
       else
 	is_dir = S_ISDIR (lstat_buf.st_mode);
@@ -786,35 +781,28 @@
 	  new_entry->path = xstrdup (file_name);
 	  new_entry->flag = entry->flag;
 	  new_entry->next = NULL;
-	  if (is_link)
+#ifdef _DIRENT_HAVE_D_TYPE
+	  /* We have filled in lstat only #ifndef
+	     _DIRENT_HAVE_D_TYPE.  Fill it in if needed.  */
+	  if (!is_link
+	      && direntry->d_type != DT_UNKNOWN
+	      && __builtin_expect (lstat64 (real_file_name, &lstat_buf), 0))
 	    {
-	      new_entry->ino = stat_buf.st_ino;
-	      new_entry->dev = stat_buf.st_dev;
+	      error (0, errno, _("Cannot lstat %s"), file_name);
+	      free (new_entry->path);
+	      free (new_entry);
+	      continue;
 	    }
-	  else
-	    {
-#ifdef _DIRENT_HAVE_D_TYPE
-	      /* We have filled in lstat only #ifndef
-		 _DIRENT_HAVE_D_TYPE.  Fill it in if needed.  */
-	      if (direntry->d_type != DT_UNKNOWN
-		  && __builtin_expect (lstat64 (real_file_name, &lstat_buf),
-				       0))
-		{
-		  error (0, errno, _("Cannot lstat %s"), file_name);
-		  free (new_entry->path);
-		  free (new_entry);
-		  continue;
-		}
 #endif
-	      new_entry->ino = lstat_buf.st_ino;
-	      new_entry->dev = lstat_buf.st_dev;
-	    }
+	  new_entry->ino = lstat_buf.st_ino;
+	  new_entry->dev = lstat_buf.st_dev;
 	  add_single_dir (new_entry, 0);
 	  continue;
 	}
       else if (!S_ISREG (lstat_buf.st_mode) && !is_link)
 	continue;
 
+      char *real_name;
       if (opt_chroot && is_link)
 	{
 	  real_name = chroot_canon (opt_chroot, file_name);
@@ -828,22 +816,25 @@
       else
 	real_name = real_file_name;
 
-      /* has_soname stores whether library has unique soname.  */
-      has_soname = 1;
-
 #ifdef _DIRENT_HAVE_D_TYPE
       /* Call lstat64 if not done yet.  */
-      if (direntry->d_type != DT_UNKNOWN
+      if (!is_link
+	  && direntry->d_type != DT_UNKNOWN
 	  && __builtin_expect (lstat64 (real_file_name, &lstat_buf), 0))
 	{
 	  error (0, errno, _("Cannot lstat %s"), file_name);
 	  continue;
 	}
 #endif
+
+      /* has_soname stores whether library has unique soname.  */
+      int has_soname = 1;
+
       /* First search whether the auxiliary cache contains this
 	 library already and it's not changed.  */
-      if (!search_aux_cache (direntry->d_name, &lstat_buf, &flag, &osversion,
-			     &soname))
+      char *soname;
+      unsigned int osversion;
+      if (!search_aux_cache (&lstat_buf, &flag, &osversion, &soname))
 	{
 	  if (process_file (real_name, file_name, direntry->d_name, &flag,
 			    &osversion, &soname, is_link, &has_soname))
@@ -916,6 +907,7 @@
 	}
 
       /* Add library to list.  */
+      struct dlib_entry *dlib_ptr;
       for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next)
 	{
 	  /* Is soname already in list?  */
@@ -943,16 +935,16 @@
 			  error (0, 0, _("libraries %s and %s in directory %s have same soname but different type."),
 				 dlib_ptr->name, direntry->d_name,
 				 entry->path);
+			  lstat_buf.st_dev = 0;
 			  lstat_buf.st_ino = 0;
-			  lstat_buf.st_ctime = 0;
 			  lstat_buf.st_size = 0;
-			  lstat_buf.st_dev = 0;
+			  lstat_buf.st_ctime = 0;
 			}
 		    }
 		  free (dlib_ptr->name);
-		  dlib_ptr->osversion = osversion;
 		  dlib_ptr->name = xstrdup (direntry->d_name);
 		  dlib_ptr->is_link = is_link;
+		  dlib_ptr->osversion = osversion;
 		  dlib_ptr->stat_buf = lstat_buf;
 		}
 	      /* Don't add this library, abort loop.  */
@@ -966,10 +958,10 @@
 	{
 	  dlib_ptr = (struct dlib_entry *)xmalloc (sizeof (struct dlib_entry));
 	  dlib_ptr->name = xstrdup (direntry->d_name);
-	  dlib_ptr->flag = flag;
-	  dlib_ptr->osversion = osversion;
 	  dlib_ptr->soname = soname;
+	  dlib_ptr->flag = flag;
 	  dlib_ptr->is_link = is_link;
+	  dlib_ptr->osversion = osversion;
 	  dlib_ptr->stat_buf = lstat_buf;
 	  /* Add at head of list.  */
 	  dlib_ptr->next = dlibs;
@@ -981,6 +973,7 @@
 
   /* Now dlibs contains a list of all libs - add those to the cache
      and created all symbolic links.  */
+  struct dlib_entry *dlib_ptr;
   for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next)
     {
       /* Don't create links to links.  */
--- libc/elf/readlib.c	3 Jul 2007 19:57:18 -0000
+++ libc/elf/readlib.c	2007-07-27 12:23:15.000000000 +0200
@@ -174,7 +174,7 @@
       if (process_elf_file (file_name, lib, flag, osversion, soname,
 			     file_contents, statbuf.st_size))
 	ret = 1;
-      else if (! *soname)
+      else if (*soname == NULL)
 	*soname = xstrdup (lib);
       else if (has_soname)
 	*has_soname = 1;
--- libc/sysdeps/generic/ldconfig.h	3 Jul 2007 19:57:20 -0000
+++ libc/sysdeps/generic/ldconfig.h	2007-07-27 12:20:28.000000000 +0200
@@ -51,9 +51,8 @@
 
 extern void load_aux_cache (const char *cache_name, const char *aux_cache_name);
 
-extern int search_aux_cache (const char *file, struct stat64 *stat_buf,
-			     int *flags, unsigned int *osversion,
-			     char **soname);
+extern int search_aux_cache (struct stat64 *stat_buf, int *flags,
+			     unsigned int *osversion, char **soname);
 
 extern void free_aux_cache (void);
 


More information about the Libc-alpha mailing list