This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
Jakub Jelinek <jakub@redhat.com> writes: > On Mon, Jul 02, 2007 at 09:35:14AM +0200, Andreas Jaeger wrote: >> + /* Check that directory exists and create if needed. */ >> + dir = xstrdup (aux_cache_name); >> + dir = dirname (dir); >> + if (stat64 (dir, &st) < 0) >> + { >> + if (mkdir (dir, 0755) < 0) >> + error (EXIT_FAILURE, errno, _("Cannot create directory %s"), dir); >> + } >> + free (dir); > >> + /* Create file. */ >> + fd = open (temp_name, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW, >> + S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR); >> + if (fd < 0) >> + error (EXIT_FAILURE, errno, >> + _("Can't create temporary auxiliary cache file %s"), >> + temp_name); > >> + /* Make sure user can always read auxiliary 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); >> + > > Why do you need /var/cache/ldconfig and /var/cache/ldconfig/ldconfig.aux-cache > world readable? While /etc/ld.so.cache clearly has to be world readable, > otherwise ld.so couldn't load it, the aux cache can be only readable by > root and although it doesn't contain a lot of sensitive data, it contains > some (ldconfig executed as root can see in non-world readable/executable > directories and the aux cache tells you ctime, ino/dev, sizes of the files > there). If you run ldconfig as normal user, it would just ignore the aux > cache (it won't be able to write ld.so.cache anyway). Ok, changed - as well as the directory permissions (to 750) > BTW, why the duplication of name? A file in /var/cache/ldconfig/ directory > is ldconfig related already by the presence in that directory, so it could > be just /var/cache/ldconfig/aux-cache. Changed as well. >> @@ -694,6 +704,7 @@ search_dir (const struct dir_entry *entr >> #endif >> !is_hwcap_platform (direntry->d_name))) >> continue; >> + >> 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. */ >> @@ -726,20 +737,15 @@ search_dir (const struct dir_entry *entr >> } >> sprintf (real_file_name, "%s/%s", dir_name, direntry->d_name); >> } >> -#ifdef _DIRENT_HAVE_D_TYPE >> - if (direntry->d_type != DT_UNKNOWN) >> - lstat_buf.st_mode = DTTOIF (direntry->d_type); >> - else >> -#endif >> - if (__builtin_expect (lstat64 (real_file_name, &lstat_buf), 0)) >> - { >> - error (0, errno, _("Cannot lstat %s"), file_name); >> - continue; >> - } >> + if (__builtin_expect (lstat64 (real_file_name, &lstat_buf), 0)) >> + { >> + error (0, errno, _("Cannot lstat %s"), file_name); >> + continue; >> + } > > Why have you changed this? It seems to me that you are removing > a useful optimization. Although before this change lstat_buf fields > other than the file type in lstat_buf.st_mode was only needed for > directories and now is needed also for regular files, still the above change > means you call lstat64 unnecessarily for symbolic links at least (where > you only care about stat_buf contains which you copy over into lstat_buf > fields). And symbolic links are roughly half of all the directory entries. Let me check the code again... The problem is that this code needs lstat_buf set up: + if (!search_aux_cache (direntry->d_name, &lstat_buf, &flag, &osversion, + &soname)) So, if I leave the optimization in - I need to handle this differently. Here's an updated patch. What do you think now? Thanks for the good review, Andreas Index: elf/cache.c =================================================================== RCS file: /cvs/glibc/libc/elf/cache.c,v retrieving revision 1.29 diff -u -p -r1.29 cache.c --- elf/cache.c 10 Nov 2006 20:15:53 -0000 1.29 +++ elf/cache.c 3 Jul 2007 19:57:17 -0000 @@ -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. @@ -32,6 +32,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. */ @@ -40,12 +48,46 @@ 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" +#define AUX_CACHE_VERSION "1.0" +#define AUX_CACHEMAGIC_VERSION AUX_CACHEMAGIC AUX_CACHE_VERSION + +struct aux_cache_file_entry +{ + int32_t flags; /* This is 1 for an ELF library. */ + uint32_t key, value; /* String table indices. */ + 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]; + 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 .*/ + 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"}; @@ -232,8 +274,8 @@ init_cache (void) -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; @@ -264,17 +306,23 @@ 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; + 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. */ @@ -342,6 +390,22 @@ save_cache (const char *cache_name) file_entries_new->len_strings = total_strlen; } + /* 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); + + /* 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); + 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; /* If we have both formats, we hide the new format in the strings @@ -351,6 +415,8 @@ save_cache (const char *cache_name) str_offset = file_entries_new_size; else str_offset = 0; + /* Initial String offset for auxiliary cache is always 0. */ + aux_str_offset = 0; str = strings; for (idx_old = 0, idx_new = 0, entry = entries; entry != NULL; @@ -374,21 +440,30 @@ save_cache (const char *cache_name) 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].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); 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; @@ -443,7 +518,7 @@ save_cache (const char *cache_name) 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, @@ -454,9 +529,70 @@ save_cache (const char *cache_name) error (EXIT_FAILURE, errno, _("Renaming of %s to %s failed"), temp_name, cache_name); + 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. */ + dir = xstrdup (aux_cache_name); + dir = dirname (dir); + if (stat64 (dir, &st) < 0) + { + if (mkdir (dir, 0750) < 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); + 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) + 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, + aux_cache_name); + /* Free all allocated memory. */ free (file_entries_new); free (file_entries); + free (aux_file_entries); free (strings); while (entries) @@ -473,7 +609,8 @@ 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; @@ -492,6 +629,10 @@ add_to_cache (const char *path, const ch 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) @@ -521,3 +662,146 @@ 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) +{ + 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); + 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) + { + 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) + { + 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; + } + + 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); + new_entry->flags = aux_cache->libs[i].flags; + new_entry->osversion = aux_cache->libs[i].osversion; + 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 (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, + 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; + free (entry->path); + free (entry->lib); + aux_entries = entry->next; + free (entry); + } +} Index: elf/ldconfig.c =================================================================== RCS file: /cvs/glibc/libc/elf/ldconfig.c,v retrieving revision 1.59 diff -u -p -r1.59 ldconfig.c --- elf/ldconfig.c 13 Apr 2007 19:53:20 -0000 1.59 +++ elf/ldconfig.c 3 Jul 2007 19:57:18 -0000 @@ -111,6 +111,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; @@ -141,6 +144,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 } }; @@ -237,10 +241,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; @@ -517,7 +526,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; @@ -572,7 +581,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); @@ -617,6 +626,7 @@ struct dlib_entry int flag; int is_link; unsigned int osversion; + struct stat64 stat_buf; struct dlib_entry *next; }; @@ -632,7 +642,7 @@ search_dir (const struct dir_entry *entr struct dlib_entry *dlibs; struct dlib_entry *dlib_ptr; struct stat64 lstat_buf, stat_buf; - int is_link, is_dir; + int is_link, is_dir, has_soname; uint64_t hwcap = path_hwcap (entry->path); unsigned int osversion; @@ -694,6 +704,7 @@ search_dir (const struct dir_entry *entr #endif !is_hwcap_platform (direntry->d_name))) continue; + 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. */ @@ -727,6 +738,7 @@ search_dir (const struct dir_entry *entr sprintf (real_file_name, "%s/%s", dir_name, direntry->d_name); } #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 @@ -739,7 +751,7 @@ search_dir (const struct dir_entry *entr 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)) @@ -753,6 +765,13 @@ search_dir (const struct dir_entry *entr continue; } is_dir = S_ISDIR (stat_buf.st_mode); +#ifndef _DIRENT_HAVE_D_TYPE + /* lstat is later stored, update contents. */ + 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 } else is_dir = S_ISDIR (lstat_buf.st_mode); @@ -786,7 +805,6 @@ search_dir (const struct dir_entry *entr continue; } #endif - new_entry->ino = lstat_buf.st_ino; new_entry->dev = lstat_buf.st_dev; } @@ -809,14 +827,31 @@ 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)) + /* 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 + && __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 + /* 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)) + { + 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) @@ -833,13 +868,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); } @@ -847,7 +884,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) { @@ -886,13 +938,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_ino = 0; + lstat_buf.st_ctime = 0; + lstat_buf.st_size = 0; + lstat_buf.st_dev = 0; + } } free (dlib_ptr->name); dlib_ptr->osversion = osversion; dlib_ptr->name = xstrdup (direntry->d_name); dlib_ptr->is_link = is_link; + dlib_ptr->stat_buf = lstat_buf; } /* Don't add this library, abort loop. */ /* Also free soname, since it's dynamically allocated. */ @@ -909,6 +969,7 @@ search_dir (const struct dir_entry *entr dlib_ptr->osversion = osversion; dlib_ptr->soname = soname; dlib_ptr->is_link = is_link; + dlib_ptr->stat_buf = lstat_buf; /* Add at head of list. */ dlib_ptr->next = dlibs; dlibs = dlib_ptr; @@ -927,7 +988,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. */ @@ -1245,7 +1306,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) : "/"); @@ -1292,10 +1353,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; } Index: elf/readlib.c =================================================================== RCS file: /cvs/glibc/libc/elf/readlib.c,v retrieving revision 1.19 diff -u -p -r1.19 readlib.c --- elf/readlib.c 21 Dec 2005 22:16:20 -0000 1.19 +++ elf/readlib.c 3 Jul 2007 19:57:18 -0000 @@ -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. @@ -68,7 +68,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; @@ -77,6 +77,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; @@ -134,7 +137,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."); @@ -165,9 +168,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) + *soname = xstrdup (lib); + else if (has_soname) + *has_soname = 1; + } done: /* Clean up allocated memory and resources. */ Index: sysdeps/generic/ldconfig.h =================================================================== RCS file: /cvs/glibc/libc/sysdeps/generic/ldconfig.h,v retrieving revision 1.6 diff -u -p -r1.6 ldconfig.h --- sysdeps/generic/ldconfig.h 14 Mar 2003 05:32:49 -0000 1.6 +++ sysdeps/generic/ldconfig.h 3 Jul 2007 19:57:20 -0000 @@ -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,32 @@ #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 (const char *file, 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, -- Andreas Jaeger, Director Platform/openSUSE, aj@suse.de SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nürnberg) Maxfeldstr. 5, 90409 Nürnberg, Germany GPG fingerprint = 93A3 365E CE47 B889 DF7F FED1 389A 563C C272 A126
Attachment:
pgp00000.pgp
Description: PGP signature
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |