diff options
author | Ulrich Drepper <drepper@redhat.com> | 2000-05-07 21:23:56 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2000-05-07 21:23:56 +0000 |
commit | 45eca4d141c047950db48c69c8941163d0a61fcd (patch) | |
tree | 66035482a9beed5f14699227294ac902b32a5106 /elf | |
parent | d89d0afad4551a808b15510795f965aed147a834 (diff) | |
download | glibc-45eca4d141c047950db48c69c8941163d0a61fcd.tar glibc-45eca4d141c047950db48c69c8941163d0a61fcd.tar.gz glibc-45eca4d141c047950db48c69c8941163d0a61fcd.tar.bz2 glibc-45eca4d141c047950db48c69c8941163d0a61fcd.zip |
Update.
2000-05-06 Bruno Haible <haible@clisp.cons.org>
* iconv/gconv_open.c (__gconv_open): If __gconv_find_transform
returned != __GCONV_OK, there is nothing to clean up.
2000-05-06 Bruno Haible <haible@clisp.cons.org>
* intl/tst-gettext.c (main): Disable possibly existing LC_CTYPE and
OUTPUT_CHARSET environment variables.
2000-05-06 Andreas Jaeger <aj@suse.de>
* sysdeps/generic/dl-cache.h (struct file_entry_new): New.
(struct cache_file_new): New.
(struct file_entry): New (moved from cache.c).
(struct cache_file): New (moved from cache.c).
* sysdeps/generic/dl-cache.c (SEARCH_CACHE): New macro, broken out
from _dl_load_cache_lookup.
(_dl_load_cache_lookup): Move search to SEARCH_CACHE macro, handle
the different cache formats.
New variable cache_new for new format.
* elf/ldconfig.h: Change according to changes in cache.c and
ldconfig.c; remove cache_libcmp; add opt_format.
* elf/ldconfig.c: Include "dl-cache.h" and "dl-procinfo.h"; remove
stuff that's defined in those headers.
Add hwcap to struct lib_entry.
(opt_format): New variable to select cache format.
(options): Add format parameter.
(is_hwcap): New function.
(path_hwcap): New function.
(parse_opt): Handle new format parameter.
(search_dir): Handle hwcap, search also subdirectories with hwcap.
* elf/cache.c (_GNU_SOURCE): Removed. Not needed anymore since
ldconfig is part of glibc.
Include dl-cache.h and remove stuff that's defined there.
(struct cache_entry): Add new member hwcap.
(print_entry): Print hwcap, cleanup a bit.
(print_cache): Print new and old formats.
(compare): Use _dl_cache_libcmp from dl-cache.h; handle hwcap.
(save_cache): Save new and old formats.
(add_to_cache): Handle hwcap.
* sysdeps/generic/dl-cache.c (_dl_cache_libcmp): Moved from here...
* sysdeps/generic/dl-cache.h (_dl_cache_libcmp): ...to here.
* sysdeps/generic/dl-cache.c (LD_SO_CACHE): Moved from here...
* sysdeps/generic/dl-cache.h (LD_SO_CACHE): ...to here.
* sysdeps/generic/dl-cache.c (CACHEMAGIC): Moved from here...
* sysdeps/generic/dl-cache.h (CACHEMAGIC): ...to here.
2000-05-05 Bruno Haible <haible@clisp.cons.org>
* intl/dcigettext.c (alignof): New macro.
(_nl_find_msg): Use it instead of __alignof__. Pass correct output
buffer length to __gconv/iconv. If malloc (freemem_size) fails, set
freemem_size to 0.
2000-05-05 Bruno Haible <haible@clisp.cons.org>
* intl/dcigettext.c (dcigettext): Fix interpretation of tsearch
return value.
Diffstat (limited to 'elf')
-rw-r--r-- | elf/cache.c | 277 | ||||
-rw-r--r-- | elf/ldconfig.c | 150 | ||||
-rw-r--r-- | elf/ldconfig.h | 11 |
3 files changed, 295 insertions, 143 deletions
diff --git a/elf/cache.c b/elf/cache.c index cc75704f54..fbbc426268 100644 --- a/elf/cache.c +++ b/elf/cache.c @@ -17,9 +17,6 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#define _GNU_SOURCE 1 - -#include <assert.h> #include <errno.h> #include <error.h> #include <dirent.h> @@ -34,32 +31,18 @@ #include <sys/types.h> #include "ldconfig.h" - -#define CACHEMAGIC "ld.so-1.7.0" +#include "dl-cache.h" struct cache_entry { - char *lib; - char *path; - int flags; - struct cache_entry *next; + char *lib; /* Library name. */ + char *path; /* Path to find library. */ + int flags; /* Flags to indicate kind of library. */ + unsigned long int hwcap; /* Important hardware capabilities. */ + int bits_hwcap; /* Number of bits set in hwcap. */ + struct cache_entry *next; /* Next entry in list. */ }; -struct file_entry -{ - int flags; /* This is 1 for an ELF library. */ - unsigned int key, value; /* String table indices. */ -}; - - -struct cache_file -{ - char magic[sizeof CACHEMAGIC - 1]; - unsigned int nlibs; - struct file_entry libs[0]; -}; - - /* List of all cache entries. */ static struct cache_entry *entries; @@ -69,7 +52,7 @@ static const char *flag_descr[] = /* Print a single entry. */ static void -print_entry (const char *lib, int flag, const char *key) +print_entry (const char *lib, int flag, unsigned long int hwcap, const char *key) { printf ("\t%s (", lib); switch (flag & FLAG_TYPE_MASK) @@ -93,14 +76,17 @@ print_entry (const char *lib, int flag, const char *key) case 0: break; default: - fprintf (stdout, ",%d", flag & FLAG_REQUIRED_MASK); + printf (",%d", flag & FLAG_REQUIRED_MASK); break; } + if (hwcap != 0) + printf (", hwcap: 0x%lx", hwcap); printf (") => %s\n", key); } -/* Print the whole cache file. */ +/* Print the whole cache file, if a file contains the new cache format + hidden in the old one, print the contents of the new format. */ void print_cache (const char *cache_name) { @@ -109,7 +95,9 @@ print_cache (const char *cache_name) 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); if (fd < 0) @@ -128,20 +116,63 @@ print_cache (const char *cache_name) error (EXIT_FAILURE, errno, _("mmap of cache file failed.\n")); cache_size = st.st_size; - if (cache_size < sizeof (struct cache_file) - || memcmp (cache->magic, CACHEMAGIC, sizeof CACHEMAGIC - 1)) - return; - /* This is where the strings start. */ - cache_data = (const char *) &cache->libs[cache->nlibs]; + if (cache_size < sizeof (struct cache_file)) + error (EXIT_FAILURE, 0, _("File is not a cache file.\n")); + + if (memcmp (cache->magic, CACHEMAGIC, sizeof CACHEMAGIC - 1)) + { + /* This can only be the new format without the old one. */ + cache_new = (struct cache_file_new *) cache; + + if (memcmp (cache_new->magic, CACHEMAGIC_NEW, sizeof CACHEMAGIC_NEW - 1) + || memcmp (cache_new->version, CACHE_VERSION, + sizeof CACHE_VERSION - 1)) + error (EXIT_FAILURE, 0, _("File is not a cache file.\n")); + format = 1; + /* This is where the strings start. */ + cache_data = (const char *) cache; + } + else + { + /* This is where the strings start. */ + cache_data = (const char *) &cache->libs[cache->nlibs]; + + /* Check for a new cache embedded in the old format. */ + if (cache_size > + (sizeof (struct cache_file) + + cache->nlibs * sizeof (struct file_entry) + + sizeof (struct cache_file_new))) + { + cache_new = (struct cache_file_new *) cache_data; - printf (_("%d libs found in cache `%s'\n"), cache->nlibs, cache_name); + if (!memcmp (cache_new->magic, CACHEMAGIC_NEW, sizeof CACHEMAGIC_NEW - 1) + && !memcmp (cache_new->version, CACHE_VERSION, + sizeof CACHE_VERSION - 1)) + format = 1; + } + } - /* Print everything. */ - for (i = 0; i < cache->nlibs; i++) - print_entry (cache_data + cache->libs[i].key, - cache->libs[i].flags, - cache_data + cache->libs[i].value); + if (format == 0) + { + printf (_("%d libs found in cache `%s'\n"), cache->nlibs, cache_name); + /* Print everything. */ + for (i = 0; i < cache->nlibs; i++) + print_entry (cache_data + cache->libs[i].key, + cache->libs[i].flags, 0, + cache_data + cache->libs[i].value); + } + else if (format == 1) + { + printf (_("%d libs found in cache `%s'\n"), cache_new->nlibs, cache_name); + + /* Print everything. */ + for (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].hwcap, + cache_data + cache_new->libs[i].value); + } /* Cleanup. */ munmap (cache, cache_size); close (fd); @@ -155,45 +186,6 @@ init_cache (void) } -/* Helper function which must match the one in the dynamic linker, so that - we rely on the same sort order. */ -int -cache_libcmp (const char *p1, const char *p2) -{ - while (*p1 != '\0') - { - if (*p1 >= '0' && *p1 <= '9') - { - if (*p2 >= '0' && *p2 <= '9') - { - /* Must compare this numerically. */ - int val1; - int val2; - - val1 = *p1++ - '0'; - val2 = *p2++ - '0'; - while (*p1 >= '0' && *p1 <= '9') - val1 = val1 * 10 + *p1++ - '0'; - while (*p2 >= '0' && *p2 <= '9') - val2 = val2 * 10 + *p2++ - '0'; - if (val1 != val2) - return val1 - val2; - } - else - return 1; - } - else if (*p2 >= '0' && *p2 <= '9') - return -1; - else if (*p1 != *p2) - return *p1 - *p2; - else - { - ++p1; - ++p2; - } - } - return *p1 - *p2; -} static int compare (const struct cache_entry *e1, const struct cache_entry *e2) @@ -201,80 +193,142 @@ 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 = cache_libcmp (e2->lib, e1->lib); + res = _dl_cache_libcmp (e2->lib, e1->lib); if (res == 0) { if (e1->flags < e2->flags) return 1; else if (e1->flags > e2->flags) return -1; + /* Sort by most specific hwcap. */ + else if (e2->bits_hwcap > e1->bits_hwcap) + return 1; + else if (e2->bits_hwcap < e1->bits_hwcap) + return -1; + else if (e2->hwcap > e1->hwcap) + return 1; + else if (e2->hwcap < e1->hwcap) + return -1; } return res; } - /* Save the contents of the cache. */ void save_cache (const char *cache_name) { struct cache_entry *entry; - int i, fd; + int fd, idx_old, idx_new; size_t total_strlen, len; char *strings, *str, *temp_name; - struct cache_file *file_entries; - size_t file_entries_size; + 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; /* 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; for (entry = entries; entry != NULL; entry = entry->next) { /* Account the final NULs. */ total_strlen += strlen (entry->lib) + strlen (entry->path) + 2; ++cache_entry_count; + if (entry->hwcap == 0) + ++cache_entry_old_count; } /* Create the on disk cache structure. */ /* First an array for all strings. */ - strings = (char *)xmalloc (total_strlen + 1); + strings = (char *)xmalloc (total_strlen); - /* And the list of all entries. */ - file_entries_size = sizeof (struct cache_file) - + cache_entry_count * sizeof (struct file_entry); - file_entries = (struct cache_file *) xmalloc (file_entries_size); + if (opt_format != 2) + { + /* 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); + + /* Fill in the header. */ + memset (file_entries, 0, sizeof (struct cache_file)); + memcpy (file_entries->magic, CACHEMAGIC, sizeof CACHEMAGIC - 1); - /* Fill in the header. */ - memset (file_entries, 0, sizeof (struct cache_file)); - memcpy (file_entries->magic, CACHEMAGIC, sizeof CACHEMAGIC - 1); + file_entries->nlibs = cache_entry_old_count; + } - file_entries->nlibs = cache_entry_count; + 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); + + /* Fill in the header. */ + 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, sizeof CACHE_VERSION - 1); + + file_entries_new->nlibs = cache_entry_count; + file_entries_new->len_strings = total_strlen; + } + + /* 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. */ + if (opt_format == 1) + str_offset = file_entries_new_size; + else + str_offset = 0; - str_offset = 0; str = strings; - for (i = 0, entry = entries; entry != NULL; entry = entry->next, ++i) + for (idx_old = 0, idx_new = 0, entry = entries; entry != NULL; + entry = entry->next, ++idx_new) { - file_entries->libs[i].flags = entry->flags; /* First the library. */ - /* XXX: Actually we can optimize here and remove duplicates. */ - file_entries->libs[i].key = str_offset; + if (opt_format != 2) + { + file_entries->libs[idx_old].flags = entry->flags; + /* XXX: Actually we can optimize here and remove duplicates. */ + file_entries->libs[idx_old].key = str_offset; + } + if (opt_format != 0) + { + /* We could subtract file_entries_new_size from str_offset - + not doing so makes the code easier, the string table + always begins at the beginning of the the new cache + struct. */ + file_entries_new->libs[idx_new].flags = entry->flags; + file_entries_new->libs[idx_new].hwcap = entry->hwcap; + file_entries_new->libs[idx_new].key = str_offset; + } len = strlen (entry->lib); str = stpcpy (str, entry->lib); /* Account the final NUL. */ ++str; str_offset += len + 1; /* Then the path. */ - file_entries->libs[i].value = str_offset; + if (opt_format != 2) + file_entries->libs[idx_old].value = str_offset; + if (opt_format != 0) + file_entries_new->libs[idx_new].value = str_offset; len = strlen (entry->path); str = stpcpy (str, entry->path); /* Account the final NUL. */ ++str; str_offset += len + 1; + /* Ignore entries with hwcap for old format. */ + if (entry->hwcap == 0) + ++idx_old; } - assert (str_offset == total_strlen); /* Write out the cache. */ @@ -293,8 +347,17 @@ save_cache (const char *cache_name) temp_name); /* Write contents. */ - if (write (fd, file_entries, file_entries_size) != (ssize_t)file_entries_size) - error (EXIT_FAILURE, errno, _("Writing of cache data failed")); + if (opt_format != 2) + { + if (write (fd, file_entries, file_entries_size) != (ssize_t)file_entries_size) + error (EXIT_FAILURE, errno, _("Writing of cache data failed")); + } + if (opt_format != 0) + { + if (write (fd, file_entries_new, file_entries_new_size) + != (ssize_t)file_entries_new_size) + error (EXIT_FAILURE, errno, _("Writing of cache data failed")); + } if (write (fd, strings, total_strlen) != (ssize_t)total_strlen) error (EXIT_FAILURE, errno, _("Writing of cache data failed.")); @@ -325,13 +388,15 @@ save_cache (const char *cache_name) } } + /* Add one library to the cache. */ void -add_to_cache (const char *path, const char *lib, int flags) +add_to_cache (const char *path, const char *lib, int flags, + unsigned long int hwcap) { struct cache_entry *new_entry, *ptr, *prev; char *full_path; - int len; + int len, i; new_entry = (struct cache_entry *) xmalloc (sizeof (struct cache_entry)); @@ -343,6 +408,14 @@ add_to_cache (const char *path, const char *lib, int flags) new_entry->lib = xstrdup (lib); new_entry->path = full_path; new_entry->flags = flags; + new_entry->hwcap = hwcap; + new_entry->bits_hwcap = 0; + + /* Count the number of bits set in the masked value. */ + for (i = 0; (~((1UL << i) - 1) & hwcap) != 0; ++i) + if ((hwcap & (1UL << i)) != 0) + ++new_entry->bits_hwcap; + /* Keep the list sorted - search for right place to insert. */ ptr = entries; diff --git a/elf/ldconfig.c b/elf/ldconfig.c index 98a4817202..ff96682c79 100644 --- a/elf/ldconfig.c +++ b/elf/ldconfig.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1999 Free Software Foundation, Inc. +/* Copyright (C) 1999, 2000 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Andreas Jaeger <aj@suse.de>, 1999. @@ -32,10 +32,12 @@ #include <sys/types.h> #include "ldconfig.h" +#include "dl-cache.h" -#ifndef LD_SO_CACHE -# define LD_SO_CACHE "/etc/ld.so.cache" -#endif +/* We don't need this here - silence the compiler. */ +#define _dl_sysdep_message(string, args...) do {} while (0); + +#include "dl-procinfo.h" #ifndef LD_SO_CONF # define LD_SO_CONF "/etc/ld.so.conf" @@ -49,6 +51,7 @@ struct lib_entry { int flags; + unsigned long int hwcap; char *lib; char *path; }; @@ -63,7 +66,7 @@ static const struct {"libc5", FLAG_ELF_LIBC5}, {"libc6", FLAG_ELF_LIBC6}, {"glibc2", FLAG_ELF_LIBC6} -}; +}; /* List of directories to handle. */ @@ -85,6 +88,10 @@ static int opt_print_cache = 0; /* Be verbose. */ int opt_verbose = 0; +/* Format to support. */ +/* 0: only libc5/glibc2; 1: both; 2: only glibc 2.2. */ +int opt_format = 1; + /* Build cache. */ static int opt_build_cache = 1; @@ -123,6 +130,7 @@ static const struct argp_option options[] = { NULL, 'f', "CONF", 0, N_("Use CONF as configuration file"), 0}, { 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', "FORMAT", 0, N_("Format to use: new, old or compat (default)"), 0}, { NULL, 0, NULL, 0, NULL, 0 } }; @@ -138,7 +146,53 @@ static struct argp argp = options, parse_opt, NULL, doc, NULL, NULL, NULL }; +/* Check if string corresponds to an important hardware capability. */ +static int +is_hwcap (const char *name) +{ + int hwcap_idx = _dl_string_hwcap (name); + + if (hwcap_idx != -1 && ((1 << hwcap_idx) & HWCAP_IMPORTANT)) + return 1; + return 0; +} + +/* Get hwcap encoding of path. */ +static unsigned long int +path_hwcap (const char *path) +{ + char *str = xstrdup (path); + char *ptr; + unsigned long int hwcap = 0; + unsigned long int h; + + size_t len; + + len = strlen (str); + if (str[len] == '/') + str[len] = '\0'; + + /* Search pathname from the end and check for hwcap strings. */ + for (;;) + { + ptr = strrchr (str, '/'); + + if (ptr == NULL) + break; + + h = _dl_string_hwcap (ptr+1); + + if (h == -1) + break; + hwcap += 1 << h; + /* Search the next part of the path. */ + *ptr = '\0'; + } + + free (str); + return hwcap; +} /* Handle program arguments. */ static error_t @@ -174,6 +228,14 @@ parse_opt (int key, char *arg, struct argp_state *state) case 'X': opt_link = 0; break; + case 'c': + if (strcmp (arg, "old") == 0) + opt_format = 0; + else if (strcmp (arg, "compat") == 0) + opt_format = 1; + else if (strcmp (arg, "new") == 0) + opt_format = 2; + break; default: return ARGP_ERR_UNKNOWN; } @@ -190,7 +252,7 @@ print_version (FILE *stream, struct argp_state *state) Copyright (C) %s Free Software Foundation, Inc.\n\ This is free software; see the source for copying conditions. There is NO\n\ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ -"), "1999"); +"), "2000"); fprintf (stream, gettext ("Written by %s.\n"), "Andreas Jaeger"); } @@ -202,10 +264,10 @@ add_dir (const char *line) char *equal_sign; struct dir_entry *entry, *ptr, *prev; unsigned int i; - + entry = xmalloc (sizeof (struct dir_entry)); entry->next = NULL; - + /* Search for an '=' sign. */ entry->path = xstrdup (line); equal_sign = strchr (entry->path, '='); @@ -235,7 +297,7 @@ add_dir (const char *line) entry->path [i] = '\0'; --i; } - + ptr = dir_entries; prev = ptr; while (ptr != NULL) @@ -270,7 +332,7 @@ create_links (const char *path, const char *libname, const char *soname) int do_link = 1; int do_remove = 1; /* XXX: The logics in this function should be simplified. */ - + /* Get complete path. */ snprintf (full_libname, sizeof full_libname, "%s/%s", path, libname); snprintf (full_soname, sizeof full_soname, "%s/%s", path, soname); @@ -405,7 +467,7 @@ manual_link (char *library) - create symbolic links to the soname for each library This has to be done separatly for each directory. - + To keep track of which libraries to add to the cache and which links to create, we save a list of all libraries. @@ -416,7 +478,7 @@ manual_link (char *library) if new library is newer, replace entry otherwise ignore this library otherwise add library to list - + For example, if the two libraries libxy.so.1.1 and libxy.so.1.2 exist and both have the same soname, e.g. libxy.so, a symbolic link is created from libxy.so.1.2 (the newer one) to libxy.so. @@ -424,7 +486,7 @@ manual_link (char *library) libxy.so.1.1. */ /* Information for one library. */ -struct dlib_entry +struct dlib_entry { char *name; char *soname; @@ -446,12 +508,18 @@ search_dir (const struct dir_entry *entry) int nchars; struct stat stat_buf; int is_link; - + unsigned long int hwcap = path_hwcap (entry->path); + dlibs = NULL; if (opt_verbose) - printf ("%s:\n", entry->path); - + { + if (hwcap != 0) + printf ("%s: (hwcap: 0x%lx)\n", entry->path, hwcap); + else + printf ("%s:\n", entry->path); + } + dir = opendir (entry->path); if (dir == NULL) { @@ -459,7 +527,7 @@ search_dir (const struct dir_entry *entry) error (0, errno, _("Can't open directory %s"), entry->path); return; } - + while ((direntry = readdir (dir)) != NULL) { @@ -468,15 +536,17 @@ search_dir (const struct dir_entry *entry) /* We only look at links and regular files. */ if (direntry->d_type != DT_UNKNOWN && direntry->d_type != DT_LNK - && direntry->d_type != DT_REG) + && direntry->d_type != DT_REG + && direntry->d_type != DT_DIR) continue; #endif /* _DIRENT_HAVE_D_TYPE */ - - /* Does this file look like a shared library? The dynamic - linker is also considered as shared library. */ - if ((strncmp (direntry->d_name, "lib", 3) != 0 - && strncmp (direntry->d_name, "ld-", 3) != 0) - || strstr (direntry->d_name, ".so") == NULL) + /* Does this file look like a shared library or is it a hwcap + subdirectory? The dynamic linker is also considered as + shared library. */ + if (((strncmp (direntry->d_name, "lib", 3) != 0 + && strncmp (direntry->d_name, "ld-", 3) != 0) + || strstr (direntry->d_name, ".so") == NULL) + && !is_hwcap (direntry->d_name)) continue; nchars = snprintf (buf, sizeof (buf), "%s/%s", entry->path, direntry->d_name); @@ -492,6 +562,16 @@ search_dir (const struct dir_entry *entry) error (0, errno, _("Can't lstat %s"), buf); continue; } + else if (S_ISDIR (stat_buf.st_mode) && is_hwcap (direntry->d_name)) + { + /* Handle subdirectory also, make a recursive call. */ + struct dir_entry new_entry; + new_entry.path = buf; + new_entry.flag = entry->flag; + new_entry.next = NULL; + search_dir (&new_entry); + continue; + } else if (!S_ISREG (stat_buf.st_mode) && !S_ISLNK (stat_buf.st_mode)) continue; @@ -506,7 +586,7 @@ search_dir (const struct dir_entry *entry) free (soname); soname = xstrdup (direntry->d_name); } - + if (flag == FLAG_ELF && (entry->flag == FLAG_ELF_LIBC5 || entry->flag == FLAG_ELF_LIBC6)) @@ -524,7 +604,7 @@ search_dir (const struct dir_entry *entry) && entry->flag != FLAG_ANY) error (0, 0, _("libc4 library %s in wrong directory"), buf); } - + /* Add library to list. */ for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next) { @@ -535,7 +615,7 @@ search_dir (const struct dir_entry *entry) is newer. */ if ((!is_link && dlib_ptr->is_link) || (is_link == dlib_ptr->is_link - && cache_libcmp (dlib_ptr->name, direntry->d_name) < 0)) + && _dl_cache_libcmp (dlib_ptr->name, direntry->d_name) < 0)) { /* It's newer - add it. */ /* Flag should be the same - sanity check. */ @@ -586,11 +666,11 @@ search_dir (const struct dir_entry *entry) if (dlib_ptr->is_link == 0) create_links (entry->path, dlib_ptr->name, dlib_ptr->soname); if (opt_build_cache) - add_to_cache (entry->path, dlib_ptr->soname, dlib_ptr->flag); + add_to_cache (entry->path, dlib_ptr->soname, dlib_ptr->flag, hwcap); } /* Free all resources. */ - while (dlibs) + while (dlibs) { dlib_ptr = dlibs; free (dlib_ptr->soname); @@ -627,7 +707,7 @@ parse_conf (const char *filename) FILE *file; char *line = NULL; size_t len = 0; - + file = fopen (filename, "r"); if (file == NULL) @@ -667,7 +747,7 @@ int main (int argc, char **argv) { int remaining; - + /* Parse and process arguments. */ argp_parse (&argp, argc, argv, 0, &remaining, NULL); @@ -685,7 +765,7 @@ main (int argc, char **argv) if (config_file == NULL) config_file = LD_SO_CONF; - + /* Chroot first. */ if (opt_chroot) { @@ -713,8 +793,8 @@ main (int argc, char **argv) exit (0); } - - + + if (opt_build_cache) init_cache (); @@ -726,7 +806,7 @@ main (int argc, char **argv) parse_conf (config_file); } - + search_dirs (); if (opt_build_cache) diff --git a/elf/ldconfig.h b/elf/ldconfig.h index 9e40714c05..ecdbb14883 100644 --- a/elf/ldconfig.h +++ b/elf/ldconfig.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1999 Free Software Foundation, Inc. +/* Copyright (C) 1999, 2000 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Andreas Jaeger <aj@suse.de>, 1999. @@ -37,10 +37,8 @@ extern void init_cache (void); extern void save_cache (const char *cache_name); -extern void add_to_cache (const char *path, const char *lib, int flags); - -extern int cache_libcmp (const char *p1, const char *p2); - +extern void add_to_cache (const char *path, const char *lib, int flags, + unsigned long int hwcap); /* Declared in readlib.c. */ extern int process_file (const char *file_name, const char *lib, int *flag, @@ -54,6 +52,8 @@ extern int process_elf_file (const char *file_name, const char *lib, int *flag, /* Declared in ldconfig.c. */ extern int opt_verbose; +extern int opt_format; + /* Prototypes for a few program-wide used functions. */ extern void *xmalloc (size_t __n); extern void *xcalloc (size_t __n, size_t __size); @@ -61,4 +61,3 @@ extern void *xrealloc (void *__p, size_t __n); extern char *xstrdup (const char *__str); #endif /* ! _LDCONFIG_H */ - |