Updated to fedora-glibc-20050208T0948
[glibc.git] / elf / ldconfig.c
blob70f3a8f402bdf9dce2958dc22f9c42eee9053053
1 /* Copyright (C) 1999-2004, 2005 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 Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the 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 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
20 #define PROCINFO_CLASS static
21 #include <alloca.h>
22 #include <argp.h>
23 #include <dirent.h>
24 #include <elf.h>
25 #include <error.h>
26 #include <errno.h>
27 #include <inttypes.h>
28 #include <libintl.h>
29 #include <stdbool.h>
30 #include <stdio.h>
31 #include <stdio_ext.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35 #include <sys/fcntl.h>
36 #include <sys/mman.h>
37 #include <sys/stat.h>
38 #include <sys/types.h>
39 #include <glob.h>
40 #include <libgen.h>
42 #include "ldconfig.h"
43 #include "dl-cache.h"
45 #include "dl-procinfo.h"
47 #ifndef LD_SO_CONF
48 # define LD_SO_CONF SYSCONFDIR "/ld.so.conf"
49 #endif
51 /* Get libc version number. */
52 #include <version.h>
54 #define PACKAGE _libc_intl_domainname
56 static const struct
58 const char *name;
59 int flag;
60 } lib_types[] =
62 {"libc4", FLAG_LIBC4},
63 {"libc5", FLAG_ELF_LIBC5},
64 {"libc6", FLAG_ELF_LIBC6},
65 {"glibc2", FLAG_ELF_LIBC6}
69 /* List of directories to handle. */
70 struct dir_entry
72 char *path;
73 int flag;
74 ino64_t ino;
75 dev_t dev;
76 struct dir_entry *next;
79 /* The list is unsorted, contains no duplicates. Entries are added at
80 the end. */
81 static struct dir_entry *dir_entries;
83 /* Flags for different options. */
84 /* Print Cache. */
85 static int opt_print_cache;
87 /* Be verbose. */
88 int opt_verbose;
90 /* Format to support. */
91 /* 0: only libc5/glibc2; 1: both; 2: only glibc 2.2. */
92 int opt_format = 1;
94 /* Build cache. */
95 static int opt_build_cache = 1;
97 /* Generate links. */
98 static int opt_link = 1;
100 /* Only process directories specified on the command line. */
101 static int opt_only_cline;
103 /* Path to root for chroot. */
104 static char *opt_chroot;
106 /* Manually link given shared libraries. */
107 static int opt_manual_link;
109 /* Cache file to use. */
110 static char *cache_file;
112 /* Configuration file. */
113 static const char *config_file;
115 /* Mask to use for important hardware capabilities. */
116 static unsigned long int hwcap_mask = HWCAP_IMPORTANT;
118 /* Name and version of program. */
119 static void print_version (FILE *stream, struct argp_state *state);
120 void (*argp_program_version_hook) (FILE *, struct argp_state *)
121 = print_version;
123 /* Definitions of arguments for argp functions. */
124 static const struct argp_option options[] =
126 { "print-cache", 'p', NULL, 0, N_("Print cache"), 0},
127 { "verbose", 'v', NULL, 0, N_("Generate verbose messages"), 0},
128 { NULL, 'N', NULL, 0, N_("Don't build cache"), 0},
129 { NULL, 'X', NULL, 0, N_("Don't generate links"), 0},
130 { NULL, 'r', N_("ROOT"), 0, N_("Change to and use ROOT as root directory"), 0},
131 { NULL, 'C', N_("CACHE"), 0, N_("Use CACHE as cache file"), 0},
132 { NULL, 'f', N_("CONF"), 0, N_("Use CONF as configuration file"), 0},
133 { NULL, 'n', NULL, 0, N_("Only process directories specified on the command line. Don't build cache."), 0},
134 { NULL, 'l', NULL, 0, N_("Manually link individual libraries."), 0},
135 { "format", 'c', N_("FORMAT"), 0, N_("Format to use: new, old or compat (default)"), 0},
136 { NULL, 0, NULL, 0, NULL, 0 }
139 #define PROCINFO_CLASS static
140 #include <dl-procinfo.c>
142 /* Short description of program. */
143 static const char doc[] = N_("Configure Dynamic Linker Run Time Bindings.");
145 /* Prototype for option handler. */
146 static error_t parse_opt (int key, char *arg, struct argp_state *state);
148 /* Data structure to communicate with argp functions. */
149 static struct argp argp =
151 options, parse_opt, NULL, doc, NULL, NULL, NULL
154 /* Check if string corresponds to an important hardware capability or
155 a platform. */
156 static int
157 is_hwcap_platform (const char *name)
159 int hwcap_idx = _dl_string_hwcap (name);
161 if (hwcap_idx != -1 && ((1 << hwcap_idx) & hwcap_mask))
162 return 1;
164 hwcap_idx = _dl_string_platform (name);
165 if (hwcap_idx != -1)
166 return 1;
168 #ifdef USE_TLS
169 if (strcmp (name, "tls") == 0)
170 return 1;
171 #endif
173 return 0;
176 /* Get hwcap (including platform) encoding of path. */
177 static uint64_t
178 path_hwcap (const char *path)
180 char *str = xstrdup (path);
181 char *ptr;
182 uint64_t hwcap = 0;
183 uint64_t h;
185 size_t len;
187 len = strlen (str);
188 if (str[len] == '/')
189 str[len] = '\0';
191 /* Search pathname from the end and check for hwcap strings. */
192 for (;;)
194 ptr = strrchr (str, '/');
196 if (ptr == NULL)
197 break;
199 h = _dl_string_hwcap (ptr + 1);
201 if (h == (uint64_t) -1)
203 h = _dl_string_platform (ptr + 1);
204 if (h == (uint64_t) -1)
206 #ifdef USE_TLS
207 if (strcmp (ptr + 1, "tls") == 0)
208 h = 63;
209 else
210 #endif
211 break;
214 hwcap += 1ULL << h;
216 /* Search the next part of the path. */
217 *ptr = '\0';
220 free (str);
221 return hwcap;
224 /* Handle program arguments. */
225 static error_t
226 parse_opt (int key, char *arg, struct argp_state *state)
228 switch (key)
230 case 'C':
231 cache_file = arg;
232 break;
233 case 'f':
234 config_file = arg;
235 break;
236 case 'l':
237 opt_manual_link = 1;
238 break;
239 case 'N':
240 opt_build_cache = 0;
241 break;
242 case 'n':
243 opt_build_cache = 0;
244 opt_only_cline = 1;
245 break;
246 case 'p':
247 opt_print_cache = 1;
248 break;
249 case 'r':
250 opt_chroot = arg;
251 break;
252 case 'v':
253 opt_verbose = 1;
254 break;
255 case 'X':
256 opt_link = 0;
257 break;
258 case 'c':
259 if (strcmp (arg, "old") == 0)
260 opt_format = 0;
261 else if (strcmp (arg, "compat") == 0)
262 opt_format = 1;
263 else if (strcmp (arg, "new") == 0)
264 opt_format = 2;
265 break;
266 default:
267 return ARGP_ERR_UNKNOWN;
270 return 0;
273 /* Print the version information. */
274 static void
275 print_version (FILE *stream, struct argp_state *state)
277 fprintf (stream, "ldconfig (GNU %s) %s\n", PACKAGE, VERSION);
278 fprintf (stream, gettext ("\
279 Copyright (C) %s Free Software Foundation, Inc.\n\
280 This is free software; see the source for copying conditions. There is NO\n\
281 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
282 "), "2005");
283 fprintf (stream, gettext ("Written by %s.\n"),
284 "Andreas Jaeger");
287 /* Add a single directory entry. */
288 static void
289 add_single_dir (struct dir_entry *entry, int verbose)
291 struct dir_entry *ptr, *prev;
293 ptr = dir_entries;
294 prev = ptr;
295 while (ptr != NULL)
297 /* Check for duplicates. */
298 if (ptr->ino == entry->ino && ptr->dev == entry->dev)
300 if (opt_verbose && verbose)
301 error (0, 0, _("Path `%s' given more than once"), entry->path);
302 /* Use the newer information. */
303 ptr->flag = entry->flag;
304 free (entry->path);
305 free (entry);
306 break;
308 prev = ptr;
309 ptr = ptr->next;
311 /* Is this the first entry? */
312 if (ptr == NULL && dir_entries == NULL)
313 dir_entries = entry;
314 else if (ptr == NULL)
315 prev->next = entry;
318 /* Add one directory to the list of directories to process. */
319 static void
320 add_dir (const char *line)
322 unsigned int i;
323 struct dir_entry *entry = xmalloc (sizeof (struct dir_entry));
324 entry->next = NULL;
326 /* Search for an '=' sign. */
327 entry->path = xstrdup (line);
328 char *equal_sign = strchr (entry->path, '=');
329 if (equal_sign)
331 *equal_sign = '\0';
332 ++equal_sign;
333 entry->flag = FLAG_ANY;
334 for (i = 0; i < sizeof (lib_types) / sizeof (lib_types[0]); ++i)
335 if (strcmp (equal_sign, lib_types[i].name) == 0)
337 entry->flag = lib_types[i].flag;
338 break;
340 if (entry->flag == FLAG_ANY)
341 error (0, 0, _("%s is not a known library type"), equal_sign);
343 else
345 entry->flag = FLAG_ANY;
348 /* Canonify path: for now only remove leading and trailing
349 whitespace and the trailing slashes slashes. */
350 i = strlen (entry->path) - 1;
352 while (isspace (entry->path[i]) && i > 0)
353 entry->path[i--] = '\0';
355 while (entry->path[i] == '/' && i > 0)
356 entry->path[i--] = '\0';
358 char *path = entry->path;
359 if (opt_chroot)
360 path = chroot_canon (opt_chroot, path);
362 struct stat64 stat_buf;
363 if (path == NULL || stat64 (path, &stat_buf))
365 if (opt_verbose)
366 error (0, errno, _("Can't stat %s"), entry->path);
367 free (entry->path);
368 free (entry);
370 else
372 entry->ino = stat_buf.st_ino;
373 entry->dev = stat_buf.st_dev;
375 add_single_dir (entry, 1);
378 if (opt_chroot)
379 free (path);
383 static int
384 chroot_stat (const char *real_path, const char *path, struct stat64 *st)
386 int ret;
387 char *canon_path;
389 if (!opt_chroot)
390 return stat64 (real_path, st);
392 ret = lstat64 (real_path, st);
393 if (ret || !S_ISLNK (st->st_mode))
394 return ret;
396 canon_path = chroot_canon (opt_chroot, path);
397 if (canon_path == NULL)
398 return -1;
400 ret = stat64 (canon_path, st);
401 free (canon_path);
402 return ret;
405 /* Create a symbolic link from soname to libname in directory path. */
406 static void
407 create_links (const char *real_path, const char *path, const char *libname,
408 const char *soname)
410 char *full_libname, *full_soname;
411 char *real_full_libname, *real_full_soname;
412 struct stat64 stat_lib, stat_so, lstat_so;
413 int do_link = 1;
414 int do_remove = 1;
415 /* XXX: The logics in this function should be simplified. */
417 /* Get complete path. */
418 full_libname = alloca (strlen (path) + strlen (libname) + 2);
419 full_soname = alloca (strlen (path) + strlen (soname) + 2);
420 sprintf (full_libname, "%s/%s", path, libname);
421 sprintf (full_soname, "%s/%s", path, soname);
422 if (opt_chroot)
424 real_full_libname = alloca (strlen (real_path) + strlen (libname) + 2);
425 real_full_soname = alloca (strlen (real_path) + strlen (soname) + 2);
426 sprintf (real_full_libname, "%s/%s", real_path, libname);
427 sprintf (real_full_soname, "%s/%s", real_path, soname);
429 else
431 real_full_libname = full_libname;
432 real_full_soname = full_soname;
435 /* Does soname already exist and point to the right library? */
436 if (chroot_stat (real_full_soname, full_soname, &stat_so) == 0)
438 if (chroot_stat (real_full_libname, full_libname, &stat_lib))
440 error (0, 0, _("Can't stat %s\n"), full_libname);
441 return;
443 if (stat_lib.st_dev == stat_so.st_dev
444 && stat_lib.st_ino == stat_so.st_ino)
445 /* Link is already correct. */
446 do_link = 0;
447 else if (lstat64 (full_soname, &lstat_so) == 0
448 && !S_ISLNK (lstat_so.st_mode))
450 error (0, 0, _("%s is not a symbolic link\n"), full_soname);
451 do_link = 0;
452 do_remove = 0;
455 else if (lstat64 (real_full_soname, &lstat_so) != 0
456 || !S_ISLNK (lstat_so.st_mode))
457 /* Unless it is a stale symlink, there is no need to remove. */
458 do_remove = 0;
460 if (opt_verbose)
461 printf ("\t%s -> %s", soname, libname);
463 if (do_link && opt_link)
465 /* Remove old link. */
466 if (do_remove)
467 if (unlink (real_full_soname))
469 error (0, 0, _("Can't unlink %s"), full_soname);
470 do_link = 0;
472 /* Create symbolic link. */
473 if (do_link && symlink (libname, real_full_soname))
475 error (0, 0, _("Can't link %s to %s"), full_soname, libname);
476 do_link = 0;
478 if (opt_verbose)
480 if (do_link)
481 fputs (_(" (changed)\n"), stdout);
482 else
483 fputs (_(" (SKIPPED)\n"), stdout);
486 else if (opt_verbose)
487 fputs ("\n", stdout);
490 /* Manually link the given library. */
491 static void
492 manual_link (char *library)
494 char *path;
495 char *real_path;
496 char *real_library;
497 char *libname;
498 char *soname;
499 struct stat64 stat_buf;
500 int flag;
501 unsigned int osversion;
503 /* Prepare arguments for create_links call. Split library name in
504 directory and filename first. Since path is allocated, we've got
505 to be careful to free at the end. */
506 path = xstrdup (library);
507 libname = strrchr (path, '/');
509 if (libname)
511 /* Successfully split names. Check if path is just "/" to avoid
512 an empty path. */
513 if (libname == path)
515 libname = library + 1;
516 path = xrealloc (path, 2);
517 strcpy (path, "/");
519 else
521 *libname = '\0';
522 ++libname;
525 else
527 /* There's no path, construct one. */
528 libname = library;
529 path = xrealloc (path, 2);
530 strcpy (path, ".");
533 if (opt_chroot)
535 real_path = chroot_canon (opt_chroot, path);
536 if (real_path == NULL)
538 error (0, errno, _("Can't find %s"), path);
539 free (path);
540 return;
542 real_library = alloca (strlen (real_path) + strlen (libname) + 2);
543 sprintf (real_library, "%s/%s", real_path, libname);
545 else
547 real_path = path;
548 real_library = library;
551 /* Do some sanity checks first. */
552 if (lstat64 (real_library, &stat_buf))
554 error (0, errno, _("Can't lstat %s"), library);
555 free (path);
556 return;
558 /* We don't want links here! */
559 else if (!S_ISREG (stat_buf.st_mode))
561 error (0, 0, _("Ignored file %s since it is not a regular file."),
562 library);
563 free (path);
564 return;
566 if (process_file (real_library, library, libname, &flag, &osversion,
567 &soname, 0))
569 error (0, 0, _("No link created since soname could not be found for %s"),
570 library);
571 free (path);
572 return;
574 create_links (real_path, path, libname, soname);
575 free (soname);
576 free (path);
580 /* Read a whole directory and search for libraries.
581 The purpose is two-fold:
582 - search for libraries which will be added to the cache
583 - create symbolic links to the soname for each library
585 This has to be done separatly for each directory.
587 To keep track of which libraries to add to the cache and which
588 links to create, we save a list of all libraries.
590 The algorithm is basically:
591 for all libraries in the directory do
592 get soname of library
593 if soname is already in list
594 if new library is newer, replace entry
595 otherwise ignore this library
596 otherwise add library to list
598 For example, if the two libraries libxy.so.1.1 and libxy.so.1.2
599 exist and both have the same soname, e.g. libxy.so, a symbolic link
600 is created from libxy.so.1.2 (the newer one) to libxy.so.
601 libxy.so.1.2 and libxy.so are added to the cache - but not
602 libxy.so.1.1. */
604 /* Information for one library. */
605 struct dlib_entry
607 char *name;
608 char *soname;
609 int flag;
610 int is_link;
611 unsigned int osversion;
612 struct dlib_entry *next;
616 static void
617 search_dir (const struct dir_entry *entry)
619 DIR *dir;
620 struct dirent64 *direntry;
621 char *file_name, *dir_name, *real_file_name, *real_name;
622 int file_name_len, real_file_name_len, len;
623 char *soname;
624 struct dlib_entry *dlibs;
625 struct dlib_entry *dlib_ptr;
626 struct stat64 lstat_buf, stat_buf;
627 int is_link, is_dir;
628 uint64_t hwcap = path_hwcap (entry->path);
629 unsigned int osversion;
631 file_name_len = PATH_MAX;
632 file_name = alloca (file_name_len);
634 dlibs = NULL;
636 if (opt_verbose)
638 if (hwcap != 0)
639 printf ("%s: (hwcap: 0x%" PRIx64 ")\n", entry->path, hwcap);
640 else
641 printf ("%s:\n", entry->path);
644 if (opt_chroot)
646 dir_name = chroot_canon (opt_chroot, entry->path);
647 real_file_name_len = PATH_MAX;
648 real_file_name = alloca (real_file_name_len);
650 else
652 dir_name = entry->path;
653 real_file_name_len = 0;
654 real_file_name = file_name;
657 if (dir_name == NULL || (dir = opendir (dir_name)) == NULL)
659 if (opt_verbose)
660 error (0, errno, _("Can't open directory %s"), entry->path);
661 if (opt_chroot && dir_name)
662 free (dir_name);
663 return;
666 while ((direntry = readdir64 (dir)) != NULL)
668 int flag;
669 #ifdef _DIRENT_HAVE_D_TYPE
670 /* We only look at links and regular files. */
671 if (direntry->d_type != DT_UNKNOWN
672 && direntry->d_type != DT_LNK
673 && direntry->d_type != DT_REG
674 && direntry->d_type != DT_DIR)
675 continue;
676 #endif /* _DIRENT_HAVE_D_TYPE */
677 /* Does this file look like a shared library or is it a hwcap
678 subdirectory? The dynamic linker is also considered as
679 shared library. */
680 if (((strncmp (direntry->d_name, "lib", 3) != 0
681 && strncmp (direntry->d_name, "ld-", 3) != 0)
682 || strstr (direntry->d_name, ".so") == NULL)
683 && (
684 #ifdef _DIRENT_HAVE_D_TYPE
685 direntry->d_type == DT_REG ||
686 #endif
687 !is_hwcap_platform (direntry->d_name)))
688 continue;
689 len = strlen (entry->path) + strlen (direntry->d_name);
690 if (len > file_name_len)
692 file_name_len = len + 1;
693 file_name = alloca (file_name_len);
694 if (!opt_chroot)
695 real_file_name = file_name;
697 sprintf (file_name, "%s/%s", entry->path, direntry->d_name);
698 if (opt_chroot)
700 len = strlen (dir_name) + strlen (direntry->d_name);
701 if (len > real_file_name_len)
703 real_file_name_len = len + 1;
704 real_file_name = alloca (real_file_name_len);
706 sprintf (real_file_name, "%s/%s", dir_name, direntry->d_name);
708 #ifdef _DIRENT_HAVE_D_TYPE
709 if (direntry->d_type != DT_UNKNOWN)
710 lstat_buf.st_mode = DTTOIF (direntry->d_type);
711 else
712 #endif
713 if (__builtin_expect (lstat64 (real_file_name, &lstat_buf), 0))
715 error (0, errno, _("Cannot lstat %s"), file_name);
716 continue;
719 is_link = S_ISLNK (lstat_buf.st_mode);
720 if (is_link)
722 /* In case of symlink, we check if the symlink refers to
723 a directory. */
724 if (__builtin_expect (stat64 (real_file_name, &stat_buf), 0))
726 if (opt_verbose)
727 error (0, errno, _("Cannot stat %s"), file_name);
729 /* Remove stale symlinks. */
730 if (strstr (direntry->d_name, ".so."))
731 unlink (real_file_name);
732 continue;
734 is_dir = S_ISDIR (stat_buf.st_mode);
736 else
737 is_dir = S_ISDIR (lstat_buf.st_mode);
739 if (is_dir && is_hwcap_platform (direntry->d_name))
741 /* Handle subdirectory later. */
742 struct dir_entry *new_entry;
744 new_entry = xmalloc (sizeof (struct dir_entry));
745 new_entry->path = xstrdup (file_name);
746 new_entry->flag = entry->flag;
747 new_entry->next = NULL;
748 if (is_link)
750 new_entry->ino = stat_buf.st_ino;
751 new_entry->dev = stat_buf.st_dev;
753 else
755 #ifdef _DIRENT_HAVE_D_TYPE
756 /* We have filled in lstat only #ifndef
757 _DIRENT_HAVE_D_TYPE. Fill it in if needed. */
758 if (direntry->d_type != DT_UNKNOWN
759 && __builtin_expect (lstat64 (real_file_name, &lstat_buf),
762 error (0, errno, _("Cannot lstat %s"), file_name);
763 free (new_entry->path);
764 free (new_entry);
765 continue;
767 #endif
769 new_entry->ino = lstat_buf.st_ino;
770 new_entry->dev = lstat_buf.st_dev;
772 add_single_dir (new_entry, 0);
773 continue;
775 else if (!S_ISREG (lstat_buf.st_mode) && !is_link)
776 continue;
778 if (opt_chroot && is_link)
780 real_name = chroot_canon (opt_chroot, file_name);
781 if (real_name == NULL)
783 if (strstr (file_name, ".so") == NULL)
784 error (0, 0, _("Input file %s not found.\n"), file_name);
785 continue;
788 else
789 real_name = real_file_name;
791 if (process_file (real_name, file_name, direntry->d_name, &flag,
792 &osversion, &soname, is_link))
794 if (real_name != real_file_name)
795 free (real_name);
796 continue;
800 /* A link may just point to itself. */
801 if (is_link)
803 /* If the path the link points to isn't its soname and it is not
804 .so symlink for ld(1) only, we treat it as a normal file. */
805 const char *real_base_name = basename (real_file_name);
807 if (strcmp (real_base_name, soname) != 0)
809 len = strlen (real_base_name);
810 if (len < strlen (".so")
811 || strcmp (real_base_name + len - strlen (".so"), ".so") != 0
812 || strncmp (real_base_name, soname, len) != 0)
813 is_link = 0;
817 if (real_name != real_file_name)
818 free (real_name);
820 if (is_link)
822 free (soname);
823 soname = xstrdup (direntry->d_name);
826 if (flag == FLAG_ELF
827 && (entry->flag == FLAG_ELF_LIBC5
828 || entry->flag == FLAG_ELF_LIBC6))
829 flag = entry->flag;
830 /* Some sanity checks to print warnings. */
831 if (opt_verbose)
833 if (flag == FLAG_ELF_LIBC5 && entry->flag != FLAG_ELF_LIBC5
834 && entry->flag != FLAG_ANY)
835 error (0, 0, _("libc5 library %s in wrong directory"), file_name);
836 if (flag == FLAG_ELF_LIBC6 && entry->flag != FLAG_ELF_LIBC6
837 && entry->flag != FLAG_ANY)
838 error (0, 0, _("libc6 library %s in wrong directory"), file_name);
839 if (flag == FLAG_LIBC4 && entry->flag != FLAG_LIBC4
840 && entry->flag != FLAG_ANY)
841 error (0, 0, _("libc4 library %s in wrong directory"), file_name);
844 /* Add library to list. */
845 for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next)
847 /* Is soname already in list? */
848 if (strcmp (dlib_ptr->soname, soname) == 0)
850 /* Prefer a file to a link, otherwise check which one
851 is newer. */
852 if ((!is_link && dlib_ptr->is_link)
853 || (is_link == dlib_ptr->is_link
854 && _dl_cache_libcmp (dlib_ptr->name, direntry->d_name) < 0))
856 /* It's newer - add it. */
857 /* Flag should be the same - sanity check. */
858 if (dlib_ptr->flag != flag)
860 if (dlib_ptr->flag == FLAG_ELF
861 && (flag == FLAG_ELF_LIBC5 || flag == FLAG_ELF_LIBC6))
862 dlib_ptr->flag = flag;
863 else if ((dlib_ptr->flag == FLAG_ELF_LIBC5
864 || dlib_ptr->flag == FLAG_ELF_LIBC6)
865 && flag == FLAG_ELF)
866 dlib_ptr->flag = flag;
867 else
868 error (0, 0, _("libraries %s and %s in directory %s have same soname but different type."),
869 dlib_ptr->name, direntry->d_name, entry->path);
871 free (dlib_ptr->name);
872 dlib_ptr->osversion = osversion;
873 dlib_ptr->name = xstrdup (direntry->d_name);
874 dlib_ptr->is_link = is_link;
876 /* Don't add this library, abort loop. */
877 /* Also free soname, since it's dynamically allocated. */
878 free (soname);
879 break;
882 /* Add the library if it's not already in. */
883 if (dlib_ptr == NULL)
885 dlib_ptr = (struct dlib_entry *)xmalloc (sizeof (struct dlib_entry));
886 dlib_ptr->name = xstrdup (direntry->d_name);
887 dlib_ptr->flag = flag;
888 dlib_ptr->osversion = osversion;
889 dlib_ptr->soname = soname;
890 dlib_ptr->is_link = is_link;
891 /* Add at head of list. */
892 dlib_ptr->next = dlibs;
893 dlibs = dlib_ptr;
897 closedir (dir);
899 /* Now dlibs contains a list of all libs - add those to the cache
900 and created all symbolic links. */
901 for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next)
903 /* Don't create links to links. */
904 if (dlib_ptr->is_link == 0)
905 create_links (dir_name, entry->path, dlib_ptr->name,
906 dlib_ptr->soname);
907 if (opt_build_cache)
908 add_to_cache (entry->path, dlib_ptr->soname, dlib_ptr->flag,
909 dlib_ptr->osversion, hwcap);
912 /* Free all resources. */
913 while (dlibs)
915 dlib_ptr = dlibs;
916 free (dlib_ptr->soname);
917 free (dlib_ptr->name);
918 dlibs = dlibs->next;
919 free (dlib_ptr);
922 if (opt_chroot && dir_name)
923 free (dir_name);
926 /* Search through all libraries. */
927 static void
928 search_dirs (void)
930 struct dir_entry *entry;
932 for (entry = dir_entries; entry != NULL; entry = entry->next)
933 search_dir (entry);
935 /* Free all allocated memory. */
936 while (dir_entries)
938 entry = dir_entries;
939 dir_entries = dir_entries->next;
940 free (entry->path);
941 free (entry);
946 static void parse_conf_include (const char *config_file, unsigned int lineno,
947 const char *prefix, bool do_chroot,
948 const char *pattern);
950 /* Parse configuration file. */
951 static void
952 parse_conf (const char *filename, const char *prefix, bool do_chroot)
954 FILE *file = NULL;
955 char *line = NULL;
956 const char *canon;
957 size_t len = 0;
958 unsigned int lineno;
959 size_t prefix_len = prefix ? strlen (prefix) : 0;
961 if (do_chroot && opt_chroot)
963 canon = chroot_canon (opt_chroot, filename);
964 if (canon)
965 file = fopen (canon, "r");
966 else
967 canon = filename;
969 else
971 canon = filename;
972 file = fopen (filename, "r");
975 if (file == NULL)
977 error (0, errno, _("Can't open configuration file %s"), canon);
978 if (canon != filename)
979 free ((char *) canon);
980 return;
983 /* No threads use this stream. */
984 __fsetlocking (file, FSETLOCKING_BYCALLER);
986 if (canon != filename)
987 free ((char *) canon);
989 lineno = 0;
992 ssize_t n = getline (&line, &len, file);
993 if (n < 0)
994 break;
996 ++lineno;
997 if (line[n - 1] == '\n')
998 line[n - 1] = '\0';
1000 /* Because the file format does not know any form of quoting we
1001 can search forward for the next '#' character and if found
1002 make it terminating the line. */
1003 *strchrnul (line, '#') = '\0';
1005 /* Remove leading whitespace. NUL is no whitespace character. */
1006 char *cp = line;
1007 while (isspace (*cp))
1008 ++cp;
1010 /* If the line is blank it is ignored. */
1011 if (cp[0] == '\0')
1012 continue;
1014 if (!strncmp (cp, "include", 7) && isblank (cp[7]))
1016 char *dir;
1017 cp += 8;
1018 while ((dir = strsep (&cp, " \t")) != NULL)
1019 if (dir[0] != '\0')
1020 parse_conf_include (filename, lineno, prefix, do_chroot, dir);
1022 else if (prefix != NULL)
1024 size_t cp_len = strlen (cp);
1025 char new_cp [prefix_len + cp_len + 1];
1026 memcpy (mempcpy (new_cp, prefix, prefix_len), cp, cp_len + 1);
1027 add_dir (new_cp);
1029 else
1030 add_dir (cp);
1032 while (!feof_unlocked (file));
1034 /* Free buffer and close file. */
1035 free (line);
1036 fclose (file);
1039 /* Handle one word in an `include' line, a glob pattern of additional
1040 config files to read. */
1041 static void
1042 parse_conf_include (const char *config_file, unsigned int lineno,
1043 const char *prefix, bool do_chroot, const char *pattern)
1045 if (opt_chroot && pattern[0] != '/')
1046 error (EXIT_FAILURE, 0,
1047 _("need absolute file name for configuration file when using -r"));
1049 char *copy = NULL;
1050 if (pattern[0] != '/' && strchr (config_file, '/') != NULL)
1052 if (asprintf (&copy, "%s/%s", dirname (strdupa (config_file)),
1053 pattern) < 0)
1054 error (EXIT_FAILURE, 0, _("memory exhausted"));
1055 pattern = copy;
1058 glob64_t gl;
1059 int result;
1060 if (do_chroot && opt_chroot)
1062 char *canon = chroot_canon (opt_chroot, pattern);
1063 result = glob64 (canon ?: pattern, 0, NULL, &gl);
1064 free (canon);
1066 else
1067 result = glob64 (pattern, 0, NULL, &gl);
1069 switch (result)
1071 case 0:
1072 for (size_t i = 0; i < gl.gl_pathc; ++i)
1073 parse_conf (gl.gl_pathv[i], prefix, false);
1074 globfree64 (&gl);
1075 break;
1077 case GLOB_NOMATCH:
1078 break;
1080 case GLOB_NOSPACE:
1081 errno = ENOMEM;
1082 case GLOB_ABORTED:
1083 if (opt_verbose)
1084 error (0, errno, _("%s:%u: cannot read directory %s"),
1085 config_file, lineno, pattern);
1086 break;
1088 default:
1089 abort ();
1090 break;
1093 if (copy)
1094 free (copy);
1097 /* Honour LD_HWCAP_MASK. */
1098 static void
1099 set_hwcap (void)
1101 char *mask = getenv ("LD_HWCAP_MASK");
1103 if (mask)
1104 hwcap_mask = strtoul (mask, NULL, 0);
1109 main (int argc, char **argv)
1111 int remaining;
1113 arch_startup (argc, argv);
1115 /* Parse and process arguments. */
1116 argp_parse (&argp, argc, argv, 0, &remaining, NULL);
1118 /* Remaining arguments are additional directories if opt_manual_link
1119 is not set. */
1120 if (remaining != argc && !opt_manual_link)
1122 int i;
1123 for (i = remaining; i < argc; ++i)
1124 if (opt_build_cache && argv[i][0] != '/')
1125 error (EXIT_FAILURE, 0,
1126 _("relative path `%s' used to build cache"),
1127 argv[i]);
1128 else
1129 add_dir (argv[i]);
1132 set_hwcap ();
1134 if (opt_chroot)
1136 /* Normalize the path a bit, we might need it for printing later. */
1137 char *endp = strchr (opt_chroot, '\0');
1138 while (endp > opt_chroot && endp[-1] == '/')
1139 --endp;
1140 *endp = '\0';
1141 if (endp == opt_chroot)
1142 opt_chroot = NULL;
1144 if (opt_chroot)
1146 /* It is faster to use chroot if we can. */
1147 if (!chroot (opt_chroot))
1149 if (chdir ("/"))
1150 error (EXIT_FAILURE, errno, _("Can't chdir to /"));
1151 opt_chroot = NULL;
1156 if (cache_file == NULL)
1158 cache_file = alloca (strlen (LD_SO_CACHE) + 1);
1159 strcpy (cache_file, LD_SO_CACHE);
1162 if (config_file == NULL)
1163 config_file = LD_SO_CONF;
1165 if (opt_print_cache)
1167 if (opt_chroot)
1169 char *p = chroot_canon (opt_chroot, cache_file);
1170 if (p == NULL)
1171 error (EXIT_FAILURE, errno, _("Can't open cache file %s\n"),
1172 cache_file);
1173 cache_file = p;
1175 print_cache (cache_file);
1176 if (opt_chroot)
1177 free (cache_file);
1178 exit (0);
1181 if (opt_chroot)
1183 /* Canonicalize the directory name of cache_file, not cache_file,
1184 because we'll rename a temporary cache file to it. */
1185 char *p = strrchr (cache_file, '/');
1186 char *canon = chroot_canon (opt_chroot,
1187 p ? (*p = '\0', cache_file) : "/");
1189 if (canon == NULL)
1191 error (EXIT_FAILURE, errno,
1192 _("Can't open cache file directory %s\n"),
1193 p ? cache_file : "/");
1196 if (p)
1197 ++p;
1198 else
1199 p = cache_file;
1201 cache_file = alloca (strlen (canon) + strlen (p) + 2);
1202 sprintf (cache_file, "%s/%s", canon, p);
1203 free (canon);
1206 if (opt_manual_link)
1208 /* Link all given libraries manually. */
1209 int i;
1211 for (i = remaining; i < argc; ++i)
1212 manual_link (argv[i]);
1214 exit (0);
1218 if (opt_build_cache)
1219 init_cache ();
1221 if (!opt_only_cline)
1223 parse_conf (config_file, NULL, true);
1225 /* Always add the standard search paths. */
1226 add_system_dir (SLIBDIR);
1227 if (strcmp (SLIBDIR, LIBDIR))
1228 add_system_dir (LIBDIR);
1230 add_arch_dirs (config_file);
1233 search_dirs ();
1235 if (opt_build_cache)
1236 save_cache (cache_file);
1238 return 0;