1 /* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Andreas Jaeger <aj@suse.de>, 1999.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
32 #include <sys/fcntl.h>
35 #include <sys/types.h>
40 /* We don't need this here - silence the compiler. */
41 #define _dl_sysdep_message(string, args...) do {} while (0);
43 #include "dl-procinfo.h"
46 # define LD_SO_CONF SYSCONFDIR "/ld.so.conf"
49 /* Get libc version number. */
52 #define PACKAGE _libc_intl_domainname
68 {"libc4", FLAG_LIBC4},
69 {"libc5", FLAG_ELF_LIBC5},
70 {"libc6", FLAG_ELF_LIBC6},
71 {"glibc2", FLAG_ELF_LIBC6}
75 /* List of directories to handle. */
80 struct dir_entry *next;
83 /* The list is unsorted, contains no duplicates. Entries are added at
85 static struct dir_entry *dir_entries;
87 /* Flags for different options. */
89 static int opt_print_cache = 0;
94 /* Format to support. */
95 /* 0: only libc5/glibc2; 1: both; 2: only glibc 2.2. */
99 static int opt_build_cache = 1;
101 /* Generate links. */
102 static int opt_link = 1;
104 /* Only process directories specified on the command line. */
105 static int opt_only_cline = 0;
107 /* Path to root for chroot. */
108 static char *opt_chroot;
110 /* Manually link given shared libraries. */
111 static int opt_manual_link = 0;
113 /* Cache file to use. */
114 static char *cache_file;
116 /* Configuration file. */
117 static const char *config_file;
119 /* Name and version of program. */
120 static void print_version (FILE *stream, struct argp_state *state);
121 void (*argp_program_version_hook) (FILE *, struct argp_state *)
124 /* Definitions of arguments for argp functions. */
125 static const struct argp_option options[] =
127 { "print-cache", 'p', NULL, 0, N_("Print cache"), 0},
128 { "verbose", 'v', NULL, 0, N_("Generate verbose messages"), 0},
129 { NULL, 'N', NULL, 0, N_("Don't build cache"), 0},
130 { NULL, 'X', NULL, 0, N_("Don't generate links"), 0},
131 { NULL, 'r', "ROOT", 0, N_("Change to and use ROOT as root directory"), 0},
132 { NULL, 'C', "CACHE", 0, N_("Use CACHE as cache file"), 0},
133 { NULL, 'f', "CONF", 0, N_("Use CONF as configuration file"), 0},
134 { NULL, 'n', NULL, 0, N_("Only process directories specified on the command line. Don't build cache."), 0},
135 { NULL, 'l', NULL, 0, N_("Manually link individual libraries."), 0},
136 { "format", 'c', "FORMAT", 0, N_("Format to use: new, old or compat (default)"), 0},
137 { NULL, 0, NULL, 0, NULL, 0 }
140 /* Short description of program. */
141 static const char doc[] = N_("Configure Dynamic Linker Run Time Bindings.");
143 /* Prototype for option handler. */
144 static error_t parse_opt (int key, char *arg, struct argp_state *state);
146 /* Data structure to communicate with argp functions. */
147 static struct argp argp =
149 options, parse_opt, NULL, doc, NULL, NULL, NULL
152 /* Check if string corresponds to an important hardware capability or
155 is_hwcap_platform (const char *name)
157 int hwcap_idx = _dl_string_hwcap (name);
159 if (hwcap_idx != -1 && ((1 << hwcap_idx) & HWCAP_IMPORTANT))
162 hwcap_idx = _dl_string_platform (name);
169 /* Get hwcap (including platform) encoding of path. */
171 path_hwcap (const char *path)
173 char *str = xstrdup (path);
184 /* Search pathname from the end and check for hwcap strings. */
187 ptr = strrchr (str, '/');
192 h = _dl_string_hwcap (ptr + 1);
194 if (h == (uint64_t) -1)
196 h = _dl_string_platform (ptr + 1);
197 if (h == (uint64_t) -1)
202 /* Search the next part of the path. */
210 /* Handle program arguments. */
212 parse_opt (int key, char *arg, struct argp_state *state)
245 if (strcmp (arg, "old") == 0)
247 else if (strcmp (arg, "compat") == 0)
249 else if (strcmp (arg, "new") == 0)
253 return ARGP_ERR_UNKNOWN;
259 /* Print the version information. */
261 print_version (FILE *stream, struct argp_state *state)
263 fprintf (stream, "ldconfig (GNU %s) %s\n", PACKAGE, VERSION);
264 fprintf (stream, gettext ("\
265 Copyright (C) %s Free Software Foundation, Inc.\n\
266 This is free software; see the source for copying conditions. There is NO\n\
267 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
269 fprintf (stream, gettext ("Written by %s.\n"),
273 /* Add a single directory entry. */
275 add_single_dir (struct dir_entry *entry, int verbose)
277 struct dir_entry *ptr, *prev;
283 /* Check for duplicates. */
284 if (strcmp (ptr->path, entry->path) == 0)
286 if (opt_verbose && verbose)
287 error (0, 0, _("Path `%s' given more than once"), entry->path);
288 /* Use the newer information. */
289 ptr->flag = entry->flag;
296 /* Is this the first entry? */
297 if (ptr == NULL && dir_entries == NULL)
299 else if (ptr == NULL)
303 /* Add one directory to the list of directories to process. */
305 add_dir (const char *line)
308 struct dir_entry *entry;
311 entry = xmalloc (sizeof (struct dir_entry));
314 /* Search for an '=' sign. */
315 entry->path = xstrdup (line);
316 equal_sign = strchr (entry->path, '=');
321 entry->flag = FLAG_ANY;
322 for (i = 0; i < sizeof (lib_types) / sizeof (lib_types [0]); ++i)
323 if (strcmp (equal_sign, lib_types[i].name) == 0)
325 entry->flag = lib_types[i].flag;
328 if (entry->flag == FLAG_ANY)
329 error (0, 0, _("%s is not a known library type"), equal_sign);
333 entry->flag = FLAG_ANY;
336 /* Canonify path: for now only remove trailing slashes. */
337 i = strlen (entry->path) - 1;
338 while (entry->path[i] == '/' && i > 0)
340 entry->path [i] = '\0';
344 add_single_dir (entry, 1);
349 chroot_stat (const char *real_path, const char *path, struct stat64 *st)
355 return stat64 (real_path, st);
357 ret = lstat64 (real_path, st);
358 if (ret || !S_ISLNK (st->st_mode))
361 canon_path = chroot_canon (opt_chroot, path);
362 if (canon_path == NULL)
365 ret = stat64 (canon_path, st);
370 /* Create a symbolic link from soname to libname in directory path. */
372 create_links (const char *real_path, const char *path, const char *libname,
375 char *full_libname, *full_soname;
376 char *real_full_libname, *real_full_soname;
377 struct stat64 stat_lib, stat_so, lstat_so;
380 /* XXX: The logics in this function should be simplified. */
382 /* Get complete path. */
383 full_libname = alloca (strlen (path) + strlen (libname) + 2);
384 full_soname = alloca (strlen (path) + strlen (soname) + 2);
385 sprintf (full_libname, "%s/%s", path, libname);
386 sprintf (full_soname, "%s/%s", path, soname);
389 real_full_libname = alloca (strlen (real_path) + strlen (libname) + 2);
390 real_full_soname = alloca (strlen (real_path) + strlen (soname) + 2);
391 sprintf (real_full_libname, "%s/%s", real_path, libname);
392 sprintf (real_full_soname, "%s/%s", real_path, soname);
396 real_full_libname = full_libname;
397 real_full_soname = full_soname;
400 /* Does soname already exist and point to the right library? */
401 if (chroot_stat (real_full_soname, full_soname, &stat_so) == 0)
403 if (chroot_stat (real_full_libname, full_libname, &stat_lib))
405 error (0, 0, _("Can't stat %s\n"), full_libname);
408 if (stat_lib.st_dev == stat_so.st_dev
409 && stat_lib.st_ino == stat_so.st_ino)
410 /* Link is already correct. */
412 else if (lstat64 (full_soname, &lstat_so) == 0
413 && !S_ISLNK (lstat_so.st_mode))
415 error (0, 0, _("%s is not a symbolic link\n"), full_soname);
420 else if (lstat64 (real_full_soname, &lstat_so) != 0
421 || !S_ISLNK (lstat_so.st_mode))
422 /* Unless it is a stale symlink, there is no need to remove. */
426 printf ("\t%s -> %s", soname, libname);
428 if (do_link && opt_link)
430 /* Remove old link. */
432 if (unlink (real_full_soname))
434 error (0, 0, _("Can't unlink %s"), full_soname);
437 /* Create symbolic link. */
438 if (do_link && symlink (libname, real_full_soname))
440 error (0, 0, _("Can't link %s to %s"), full_soname, libname);
446 fputs (_(" (changed)\n"), stdout);
448 fputs (_(" (SKIPPED)\n"), stdout);
451 else if (opt_verbose)
452 fputs ("\n", stdout);
455 /* Manually link the given library. */
457 manual_link (char *library)
464 struct stat64 stat_buf;
467 /* Prepare arguments for create_links call. Split library name in
468 directory and filename first. Since path is allocated, we've got
469 to be careful to free at the end. */
470 path = xstrdup (library);
471 libname = strrchr (path, '/');
475 /* Successfully split names. Check if path is just "/" to avoid
479 libname = library + 1;
480 path = xrealloc (path, 2);
491 /* There's no path, construct one. */
493 path = xrealloc (path, 2);
499 real_path = chroot_canon (opt_chroot, path);
500 if (real_path == NULL)
502 error (0, errno, _("Can't find %s"), path);
506 real_library = alloca (strlen (real_path) + strlen (libname) + 2);
507 sprintf (real_library, "%s/%s", real_path, libname);
512 real_library = library;
515 /* Do some sanity checks first. */
516 if (lstat64 (real_library, &stat_buf))
518 error (0, errno, _("Can't lstat %s"), library);
522 /* We don't want links here! */
523 else if (!S_ISREG (stat_buf.st_mode))
525 error (0, 0, _("Ignored file %s since it is not a regular file."),
530 if (process_file (real_library, library, libname, &flag, &soname, 0))
532 error (0, 0, _("No link created since soname could not be found for %s"),
537 create_links (real_path, path, libname, soname);
543 /* Read a whole directory and search for libraries.
544 The purpose is two-fold:
545 - search for libraries which will be added to the cache
546 - create symbolic links to the soname for each library
548 This has to be done separatly for each directory.
550 To keep track of which libraries to add to the cache and which
551 links to create, we save a list of all libraries.
553 The algorithm is basically:
554 for all libraries in the directory do
555 get soname of library
556 if soname is already in list
557 if new library is newer, replace entry
558 otherwise ignore this library
559 otherwise add library to list
561 For example, if the two libraries libxy.so.1.1 and libxy.so.1.2
562 exist and both have the same soname, e.g. libxy.so, a symbolic link
563 is created from libxy.so.1.2 (the newer one) to libxy.so.
564 libxy.so.1.2 and libxy.so are added to the cache - but not
567 /* Information for one library. */
574 struct dlib_entry *next;
579 search_dir (const struct dir_entry *entry)
582 struct dirent *direntry;
583 char *file_name, *dir_name, *real_file_name, *real_name;
584 int file_name_len, real_file_name_len, len;
586 struct dlib_entry *dlibs;
587 struct dlib_entry *dlib_ptr;
588 struct stat64 stat_buf;
590 uint64_t hwcap = path_hwcap (entry->path);
592 file_name_len = PATH_MAX;
593 file_name = alloca (file_name_len);
600 printf ("%s: (hwcap: 0x%Lx)\n", entry->path, hwcap);
602 printf ("%s:\n", entry->path);
607 dir_name = chroot_canon (opt_chroot, entry->path);
608 real_file_name_len = PATH_MAX;
609 real_file_name = alloca (real_file_name_len);
613 dir_name = entry->path;
614 real_file_name_len = 0;
615 real_file_name = file_name;
618 if (dir_name == NULL || (dir = opendir (dir_name)) == NULL)
621 error (0, errno, _("Can't open directory %s"), entry->path);
622 if (opt_chroot && dir_name)
627 while ((direntry = readdir (dir)) != NULL)
630 #ifdef _DIRENT_HAVE_D_TYPE
631 /* We only look at links and regular files. */
632 if (direntry->d_type != DT_UNKNOWN
633 && direntry->d_type != DT_LNK
634 && direntry->d_type != DT_REG
635 && direntry->d_type != DT_DIR)
637 #endif /* _DIRENT_HAVE_D_TYPE */
638 /* Does this file look like a shared library or is it a hwcap
639 subdirectory? The dynamic linker is also considered as
641 if (((strncmp (direntry->d_name, "lib", 3) != 0
642 && strncmp (direntry->d_name, "ld-", 3) != 0)
643 || strstr (direntry->d_name, ".so") == NULL)
644 && !is_hwcap_platform (direntry->d_name))
646 len = strlen (entry->path) + strlen (direntry->d_name);
647 if (len > file_name_len)
649 file_name_len = len + 1;
650 file_name = alloca (file_name_len);
652 real_file_name = file_name;
654 sprintf (file_name, "%s/%s", entry->path, direntry->d_name);
657 len = strlen (dir_name) + strlen (direntry->d_name);
658 if (len > real_file_name_len)
660 real_file_name_len = len + 1;
661 real_file_name = alloca (real_file_name_len);
663 sprintf (real_file_name, "%s/%s", dir_name, direntry->d_name);
665 #ifdef _DIRENT_HAVE_D_TYPE
666 if (direntry->d_type != DT_UNKNOWN)
667 stat_buf.st_mode = DTTOIF (direntry->d_type);
670 if (lstat64 (real_file_name, &stat_buf))
672 error (0, errno, _("Can't lstat %s"), file_name);
676 if (S_ISDIR (stat_buf.st_mode) && is_hwcap_platform (direntry->d_name))
678 /* Handle subdirectory later. */
679 struct dir_entry *new_entry;
681 new_entry = xmalloc (sizeof (struct dir_entry));
682 new_entry->path = xstrdup (file_name);
683 new_entry->flag = entry->flag;
684 new_entry->next = NULL;
685 add_single_dir (new_entry, 0);
688 else if (!S_ISREG (stat_buf.st_mode) && !S_ISLNK (stat_buf.st_mode))
691 is_link = S_ISLNK (stat_buf.st_mode);
692 if (opt_chroot && is_link)
694 real_name = chroot_canon (opt_chroot, file_name);
695 if (real_name == NULL)
697 if (strstr (file_name, ".so") == NULL)
698 error (0, 0, _("Input file %s not found.\n"), file_name);
703 real_name = real_file_name;
705 if (process_file (real_name, file_name, direntry->d_name, &flag,
708 if (real_name != real_file_name)
713 if (real_name != real_file_name)
716 /* Links will just point to itself. */
720 soname = xstrdup (direntry->d_name);
724 && (entry->flag == FLAG_ELF_LIBC5
725 || entry->flag == FLAG_ELF_LIBC6))
727 /* Some sanity checks to print warnings. */
730 if (flag == FLAG_ELF_LIBC5 && entry->flag != FLAG_ELF_LIBC5
731 && entry->flag != FLAG_ANY)
732 error (0, 0, _("libc5 library %s in wrong directory"), file_name);
733 if (flag == FLAG_ELF_LIBC6 && entry->flag != FLAG_ELF_LIBC6
734 && entry->flag != FLAG_ANY)
735 error (0, 0, _("libc6 library %s in wrong directory"), file_name);
736 if (flag == FLAG_LIBC4 && entry->flag != FLAG_LIBC4
737 && entry->flag != FLAG_ANY)
738 error (0, 0, _("libc4 library %s in wrong directory"), file_name);
741 /* Add library to list. */
742 for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next)
744 /* Is soname already in list? */
745 if (strcmp (dlib_ptr->soname, soname) == 0)
747 /* Prefer a file to a link, otherwise check which one
749 if ((!is_link && dlib_ptr->is_link)
750 || (is_link == dlib_ptr->is_link
751 && _dl_cache_libcmp (dlib_ptr->name, direntry->d_name) < 0))
753 /* It's newer - add it. */
754 /* Flag should be the same - sanity check. */
755 if (dlib_ptr->flag != flag)
757 if (dlib_ptr->flag == FLAG_ELF
758 && (flag == FLAG_ELF_LIBC5 || flag == FLAG_ELF_LIBC6))
759 dlib_ptr->flag = flag;
760 else if ((dlib_ptr->flag == FLAG_ELF_LIBC5
761 || dlib_ptr->flag == FLAG_ELF_LIBC6)
763 dlib_ptr->flag = flag;
765 error (0, 0, _("libraries %s and %s in directory %s have same soname but different type."),
766 dlib_ptr->name, direntry->d_name, entry->path);
768 free (dlib_ptr->name);
769 dlib_ptr->name = xstrdup (direntry->d_name);
770 dlib_ptr->is_link = is_link;
772 /* Don't add this library, abort loop. */
773 /* Also free soname, since it's dynamically allocated. */
778 /* Add the library if it's not already in. */
779 if (dlib_ptr == NULL)
781 dlib_ptr = (struct dlib_entry *)xmalloc (sizeof (struct dlib_entry));
782 dlib_ptr->name = xstrdup (direntry->d_name);
783 dlib_ptr->flag = flag;
784 dlib_ptr->soname = soname;
785 dlib_ptr->is_link = is_link;
786 /* Add at head of list. */
787 dlib_ptr->next = dlibs;
794 /* Now dlibs contains a list of all libs - add those to the cache
795 and created all symbolic links. */
796 for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next)
798 /* Don't create links to links. */
799 if (dlib_ptr->is_link == 0)
800 create_links (dir_name, entry->path, dlib_ptr->name,
803 add_to_cache (entry->path, dlib_ptr->soname, dlib_ptr->flag, hwcap);
806 /* Free all resources. */
810 free (dlib_ptr->soname);
811 free (dlib_ptr->name);
816 if (opt_chroot && dir_name)
820 /* Search through all libraries. */
824 struct dir_entry *entry;
826 for (entry = dir_entries; entry != NULL; entry = entry->next)
829 /* Free all allocated memory. */
833 dir_entries = dir_entries->next;
840 /* Parse configuration file. */
842 parse_conf (const char *filename)
851 canon = chroot_canon (opt_chroot, filename);
853 file = fopen (canon, "r");
860 file = fopen (filename, "r");
865 error (0, errno, _("Can't open configuration file %s"), canon);
866 if (canon != filename)
867 free ((char *) canon);
871 if (canon != filename)
872 free ((char *) canon);
876 ssize_t n = getline (&line, &len, file);
880 if (line[n - 1] == '\n')
883 /* Because the file format does not know any form of quoting we
884 can search forward for the next '#' character and if found
885 make it terminating the line. */
886 *strchrnul (line, '#') = '\0';
888 /* If the line is blank it is ignored. */
893 } while (!feof (file));
895 /* Free buffer and close file. */
902 main (int argc, char **argv)
906 /* Parse and process arguments. */
907 argp_parse (&argp, argc, argv, 0, &remaining, NULL);
909 /* Remaining arguments are additional libraries if opt_manual_link
911 if (remaining != argc && !opt_manual_link)
914 for (i = remaining; i < argc; ++i)
920 /* Normalize the path a bit, we might need it for printing later. */
921 char *endp = strchr (opt_chroot, '\0');
922 while (endp > opt_chroot && endp[-1] == '/')
925 if (endp == opt_chroot)
930 /* It is faster to use chroot if we can. */
931 if (!chroot (opt_chroot))
934 error (EXIT_FAILURE, errno, _("Can't chdir to /"));
940 if (cache_file == NULL)
942 cache_file = alloca (strlen (LD_SO_CACHE) + 1);
943 strcpy (cache_file, LD_SO_CACHE);
946 if (config_file == NULL)
947 config_file = LD_SO_CONF;
953 char *p = chroot_canon (opt_chroot, cache_file);
955 error (EXIT_FAILURE, errno, _("Can't open cache file %s\n"),
959 print_cache (cache_file);
967 /* Canonicalize the directory name of cache_file, not cache_file,
968 because we'll rename a temporary cache file to it. */
969 char *p = strrchr (cache_file, '/');
970 char *canon = chroot_canon (opt_chroot,
971 p ? (*p = '\0', cache_file) : "/");
975 error (EXIT_FAILURE, errno,
976 _("Can't open cache file directory %s\n"),
977 p ? cache_file : "/");
985 cache_file = alloca (strlen (canon) + strlen (p) + 2);
986 sprintf (cache_file, "%s/%s", canon, p);
992 /* Link all given libraries manually. */
995 for (i = remaining; i < argc; ++i)
996 manual_link (argv [i]);
1002 if (opt_build_cache)
1005 if (!opt_only_cline)
1007 /* Always add the standard search paths. */
1009 if (strcmp (SLIBDIR, LIBDIR))
1012 parse_conf (config_file);
1017 if (opt_build_cache)
1018 save_cache (cache_file);