aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1999-12-04 08:00:00 +0000
committerUlrich Drepper <drepper@redhat.com>1999-12-04 08:00:00 +0000
commit591e1ffbf8db5e059b9bcf3bde6d7758f018a46d (patch)
treeb5e9db8cae0b20da5dfceb7c8e4bd91f84e3ac74
parent589328764d60283e16442c9c9dcf818346356776 (diff)
downloadglibc-591e1ffbf8db5e059b9bcf3bde6d7758f018a46d.tar.xz
glibc-591e1ffbf8db5e059b9bcf3bde6d7758f018a46d.zip
Update.
1999-11-30 Andreas Jaeger <aj@suse.de> Add ldconfig: * elf/Makefile (extra-objs): Added ldconfig-modules. (ldconfig-modules): New. Added vpath for xstrdup and xmalloc. Check for use-ldconfig instead of has-ldconfig. ($(objpfx)ldconfig): New rule with dependencies. (distribute): Add new files. * sysdeps/unix/sysv/linux/sparc/readelflib.c: New file, developed together with Jakub Jelinek <jakub@redhat.com>. * sysdeps/generic/readelflib.c: Likewise. * elf/cache.c: New file. * elf/ldconfig.c: New file. * elf/ldconfig.h: New file. * elf/readlib.c: New file. * Makefile (install): Remove flag -d in ldconfig call. * configure.in: Rename has_ldconfig to use_ldconfig, set it to no by default. * config.make.in (has-ldconfig): Renamed to use-ldconfig, changed comment.
-rw-r--r--ChangeLog27
-rw-r--r--NEWS2
-rw-r--r--config.make.in5
-rw-r--r--configure.in3
-rw-r--r--elf/Makefile14
-rw-r--r--elf/cache.c363
-rw-r--r--elf/ldconfig.c647
-rw-r--r--elf/ldconfig.h63
-rw-r--r--elf/readlib.c160
-rw-r--r--manual/time.texi2
-rw-r--r--sysdeps/generic/readelflib.c180
-rw-r--r--sysdeps/unix/sysv/linux/sparc/readelflib.c57
12 files changed, 1516 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog
index 4153842209..1dd355f3e4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,30 @@
+1999-11-30 Andreas Jaeger <aj@suse.de>
+
+ Add ldconfig:
+ * elf/Makefile (extra-objs): Added ldconfig-modules.
+ (ldconfig-modules): New.
+ Added vpath for xstrdup and xmalloc.
+ Check for use-ldconfig instead of has-ldconfig.
+ ($(objpfx)ldconfig): New rule with dependencies.
+ (distribute): Add new files.
+
+ * sysdeps/unix/sysv/linux/sparc/readelflib.c: New file,
+ developed together with Jakub Jelinek <jakub@redhat.com>.
+ * sysdeps/generic/readelflib.c: Likewise.
+
+ * elf/cache.c: New file.
+ * elf/ldconfig.c: New file.
+ * elf/ldconfig.h: New file.
+ * elf/readlib.c: New file.
+
+ * Makefile (install): Remove flag -d in ldconfig call.
+
+ * configure.in: Rename has_ldconfig to use_ldconfig, set it to no
+ by default.
+
+ * config.make.in (has-ldconfig): Renamed to use-ldconfig, changed
+ comment.
+
1999-12-03 Ulrich Drepper <drepper@cygnus.com>
* sysdeps/generic/bits/stropts.h: Update with LiS types and
diff --git a/NEWS b/NEWS
index a01e97720c..b5552e8d49 100644
--- a/NEWS
+++ b/NEWS
@@ -20,6 +20,8 @@ Version 2.2
* Functions feenableexcept and fedisableexcept to control the
behaviour of individual exceptions have been added by Andreas Jaeger.
+* ldconfig program added by Andreas Jaeger and Jakub Jelinek.
+
Version 2.1.2
diff --git a/config.make.in b/config.make.in
index 4ba8143f4d..06585d2259 100644
--- a/config.make.in
+++ b/config.make.in
@@ -15,9 +15,8 @@ sysconfdir = @libc_cv_sysconfdir@
libexecdir = @libexecdir@
rootsbindir = @libc_cv_rootsbindir@
-# If ldconfig exists. This will go away as soon as `ldconfig' is available
-# in GNU libc.
-has-ldconfig = @has_ldconfig@
+# Should we use and build ldconfig?
+use-ldconfig = @use_ldconfig@
# Maybe the `ldd' script must be rewritten.
ldd-rewrite-script = @ldd_rewrite_script@
diff --git a/configure.in b/configure.in
index d7ff75bdd0..6d86b68a8b 100644
--- a/configure.in
+++ b/configure.in
@@ -1168,6 +1168,7 @@ libc_link_dests=
libc_link_sources=
# They also can set these variables.
+use_ldconfig=no
ldd_rewrite_script=no
# Iterate over all the sysdep directories we will use, running their
@@ -1282,7 +1283,7 @@ AC_SUBST(libc_cv_slibdir)
AC_SUBST(libc_cv_sysconfdir)
AC_SUBST(libc_cv_rootsbindir)
-AC_SUBST(has_ldconfig)
+AC_SUBST(use_ldconfig)
AC_SUBST(ldd_rewrite_script)
AC_SUBST(gnu_ld) AC_SUBST(gnu_as) AC_SUBST(elf)
diff --git a/elf/Makefile b/elf/Makefile
index ff5f44a819..422d278ce2 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -41,7 +41,8 @@ distribute := $(rtld-routines:=.c) dynamic-link.h do-rel.h dl-machine.h \
dl-librecon.h interp.c sln.c dl-dst.h hp-timing.h \
do-lookup.h sprof.c gen-trusted-dirs.awk \
testobj1.c testobj2.c testobj3.c testobj4.c testobj5.c \
- testobj6.c testobj1_1.c failobj.c
+ testobj6.c testobj1_1.c failobj.c \
+ ldconfig.h ldconfig.c cache.c readlib.c readelflib.c
include ../Makeconfig
@@ -64,10 +65,17 @@ install-bin += sprof
others-static = sln
install-rootsbin = sln
-ifeq (yes,$(has-ldconfig))
+ifeq (yes,$(use-ldconfig))
others-static += ldconfig
others += ldconfig
install-rootsbin += ldconfig
+
+ldconfig-modules := cache readlib xmalloc xstrdup
+extra-objs += $(ldconfig-modules:=.o)
+
+# To find xmalloc.c and xstrdup.c
+vpath %.c ../locale/programs
+
endif
ifeq (yes,$(build-shared))
@@ -191,6 +199,8 @@ $(objpfx)ldd: ldd.bash.in $(common-objpfx)soversions.mk \
$(objpfx)sprof: $(libdl)
+$(objpfx)ldconfig: $(ldconfig-modules:%=$(objpfx)%.o)
+
test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names)))
generated += $(addsuffix .so,$(modules-names))
diff --git a/elf/cache.c b/elf/cache.c
new file mode 100644
index 0000000000..d13e4dbbd7
--- /dev/null
+++ b/elf/cache.c
@@ -0,0 +1,363 @@
+/* Copyright (C) 1999 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <aj@suse.de>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ 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>
+#include <libintl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "ldconfig.h"
+
+#define CACHEMAGIC "ld.so-1.7.0"
+
+struct cache_entry
+{
+ char *lib;
+ char *path;
+ int flags;
+ struct cache_entry *next;
+};
+
+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;
+
+static const char *flag_descr[] =
+{ "libc4", "ELF", "libc5", "libc6"};
+
+
+/* Print a single entry. */
+static void
+print_entry (const char *lib, int flag, const char *key)
+{
+ printf ("\t%s (", lib);
+ switch (flag)
+ {
+ case FLAG_LIBC4:
+ case FLAG_ELF:
+ case FLAG_ELF_LIBC5:
+ case FLAG_ELF_LIBC6:
+ fputs (flag_descr [flag & FLAG_TYPE_MASK], stdout);
+ break;
+ default:
+ fputs ("unknown", stdout);
+ break;
+ }
+ switch (flag & FLAG_REQUIRED_MASK)
+ {
+#ifdef __sparc__
+ case FLAG_SPARC_LIB64:
+ fputs (",64bit", stdout);
+#endif
+ case 0:
+ break;
+ default:
+ fprintf (stdout, ",%d", flag & FLAG_REQUIRED_MASK);
+ break;
+ }
+ printf (") => %s\n", key);
+}
+
+
+/* Print the whole cache file. */
+void
+print_cache (const char *cache_name)
+{
+ size_t cache_size;
+ struct stat st;
+ int fd;
+ unsigned int i;
+ struct cache_file *cache;
+ const char *cache_data;
+
+ fd = open (cache_name, O_RDONLY);
+ if (fd < 0)
+ error (EXIT_FAILURE, errno, _("Can't open cache file %s\n"), cache_name);
+
+ if (fstat (fd, &st) < 0
+ /* No need to map the file if it is empty. */
+ || st.st_size == 0)
+ {
+ close (fd);
+ return;
+ }
+
+ cache = mmap (0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
+ if (cache == MAP_FAILED)
+ 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];
+
+ 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,
+ cache_data + cache->libs[i].value);
+
+ /* Cleanup. */
+ munmap (cache, cache_size);
+ close (fd);
+}
+
+/* Initialize cache data structures. */
+void
+init_cache (void)
+{
+ entries = NULL;
+}
+
+
+/* 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)
+{
+ int res;
+
+ /* We need to swap entries here to get the correct sort order. */
+ res = cache_libcmp (e2->lib, e1->lib);
+ if (res == 0)
+ {
+ if (e1->flags < e2->flags)
+ return 1;
+ else if (e1->flags > e2->flags)
+ return -1;
+ }
+ return res;
+}
+
+
+/* Save the contents of the cache. */
+void
+save_cache (const char *cache_name)
+{
+ struct cache_entry *entry;
+ int i, fd;
+ size_t total_strlen, len;
+ char *strings, *str, *temp_name;
+ struct cache_file *file_entries;
+ size_t file_entries_size;
+ unsigned int str_offset;
+ /* Number of cache entries. */
+ int cache_entry_count = 0;
+
+ /* The cache entries are sorted already, save them in this order. */
+
+ /* Count the length of all strings. */
+ 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;
+ }
+
+ /* Create the on disk cache structure. */
+ /* First an array for all strings. */
+ strings = (char *)xmalloc (total_strlen + 1);
+
+ /* 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);
+
+ /* 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_count;
+
+ str_offset = 0;
+ str = strings;
+ for (i = 0, entry = entries; entry != NULL; entry = entry->next, ++i)
+ {
+ 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;
+ 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;
+ len = strlen (entry->path);
+ str = stpcpy (str, entry->path);
+ /* Account the final NUL. */
+ ++str;
+ str_offset += len + 1;
+ }
+ assert (str_offset == total_strlen);
+
+ /* Write out the cache. */
+
+ /* Write cache first to a temporary file and rename it later. */
+ 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, 0644);
+ if (fd < 0)
+ error (EXIT_FAILURE, errno, _("Can't create temporary cache file %s"),
+ 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 (write (fd, strings, total_strlen) != (ssize_t)total_strlen)
+ error (EXIT_FAILURE, errno, _("Writing of cache data failed."));
+
+ close (fd);
+
+ /* 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);
+
+ /* Free all allocated memory. */
+ free (file_entries);
+ free (strings);
+
+ while (entries)
+ {
+ entry = entries;
+ free (entry->path);
+ free (entry->lib);
+ entries = entries->next;
+ free (entry);
+ }
+}
+
+/* Add one library to the cache. */
+void
+add_to_cache (const char *path, const char *lib, int flags)
+{
+ struct cache_entry *new_entry, *ptr, *prev;
+ char *full_path;
+ int len;
+
+ 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;
+ new_entry->flags = flags;
+
+ /* Keep the list sorted - search for right place to insert. */
+ ptr = entries;
+ prev = entries;
+ while (ptr != NULL)
+ {
+ if (compare (ptr, new_entry) > 0)
+ break;
+ prev = ptr;
+ ptr = ptr->next;
+ }
+ /* Is this the first entry? */
+ if (ptr == entries)
+ {
+ new_entry->next = entries;
+ entries = new_entry;
+ }
+ else
+ {
+ new_entry->next = prev->next;
+ prev->next = new_entry;
+ }
+}
diff --git a/elf/ldconfig.c b/elf/ldconfig.c
new file mode 100644
index 0000000000..6c2bcb2d4f
--- /dev/null
+++ b/elf/ldconfig.c
@@ -0,0 +1,647 @@
+/* Copyright (C) 1999 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <aj@suse.de>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <argp.h>
+#include <dirent.h>
+#include <error.h>
+#include <errno.h>
+#include <libintl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "ldconfig.h"
+
+#ifndef LD_SO_CACHE
+# define LD_SO_CACHE "/etc/ld.so.cache"
+#endif
+
+#ifndef LD_SO_CONF
+# define LD_SO_CONF "/etc/ld.so.conf"
+#endif
+
+/* Get libc version number. */
+#include <version.h>
+
+#define PACKAGE _libc_intl_domainname
+
+struct lib_entry
+ {
+ int flags;
+ char *lib;
+ char *path;
+ };
+
+static const struct
+{
+ const char *name;
+ int flag;
+} lib_types [] =
+{
+ {"libc4", FLAG_LIBC4},
+ {"libc5", FLAG_ELF_LIBC5},
+ {"libc6", FLAG_ELF_LIBC6},
+ {"glibc2", FLAG_ELF_LIBC6}
+};
+
+
+/* List of directories to handle. */
+struct dir_entry
+{
+ char *path;
+ int flag;
+ struct dir_entry *next;
+};
+
+/* The list is unsorted, contains no duplicates. Entries are added at
+ the end. */
+static struct dir_entry *dir_entries;
+
+/* Flags for different options. */
+/* Print Cache. */
+static int opt_print_cache = 0;
+
+/* Be verbose. */
+int opt_verbose = 0;
+
+/* Build cache. */
+static int opt_build_cache = 1;
+
+/* Generate links. */
+static int opt_link = 1;
+
+/* Only process directories specified on the command line. */
+static int opt_only_cline = 0;
+
+/* Path to root for chroot. */
+static char *opt_chroot;
+
+/* Cache file to use. */
+static const char *cache_file;
+
+/* Configuration file. */
+static const char *config_file;
+
+/* Name and version of program. */
+static void print_version (FILE *stream, struct argp_state *state);
+void (*argp_program_version_hook) (FILE *, struct argp_state *)
+ = print_version;
+
+/* Definitions of arguments for argp functions. */
+static const struct argp_option options[] =
+{
+ { "print-cache", 'p', NULL, 0, N_("Print cache"), 0},
+ { "verbose", 'v', NULL, 0, N_("Generate verbose messages"), 0},
+ { NULL, 'N', NULL, 0, N_("Don't build cache"), 0},
+ { NULL, 'X', NULL, 0, N_("Don't generate links"), 0},
+ { NULL, 'r', "ROOT", 0, N_("Change to and use ROOT as root directory"), 0},
+ { NULL, 'C', "CACHE", 0, N_("Use CACHE as cache file"), 0},
+ { 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, 0, NULL, 0, NULL, 0 }
+};
+
+/* Short description of program. */
+static const char doc[] = N_("Configure Dynamic Linker Run Time Bindings.");
+
+/* Prototype for option handler. */
+static error_t parse_opt (int key, char *arg, struct argp_state *state);
+
+/* Data structure to communicate with argp functions. */
+static struct argp argp =
+{
+ options, parse_opt, NULL, doc, NULL, NULL, NULL
+};
+
+
+
+/* Handle program arguments. */
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+ switch (key)
+ {
+ case 'C':
+ cache_file = arg;
+ break;
+ case 'f':
+ config_file = arg;
+ break;
+ case 'N':
+ opt_build_cache = 0;
+ break;
+ case 'n':
+ opt_build_cache = 0;
+ opt_only_cline = 1;
+ break;
+ case 'p':
+ opt_print_cache = 1;
+ break;
+ case 'r':
+ opt_chroot = arg;
+ break;
+ case 'v':
+ opt_verbose = 1;
+ break;
+ case 'X':
+ opt_link = 0;
+ break;
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+
+ return 0;
+}
+
+/* Print the version information. */
+static void
+print_version (FILE *stream, struct argp_state *state)
+{
+ fprintf (stream, "ldconfig (GNU %s) %s\n", PACKAGE, VERSION);
+ fprintf (stream, gettext ("\
+Copyright (C) %s Free Software Foundation, Inc.\n\
+This is free software; see the source for copying conditions.