]> git.ipfire.org Git - thirdparty/glibc.git/blame - elf/ldconfig.c
* sysdeps/m68k/fpu/e_log2f.c: Fix typo.
[thirdparty/glibc.git] / elf / ldconfig.c
CommitLineData
06a60d9c 1/* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
591e1ffb
UD
2 This file is part of the GNU C Library.
3 Contributed by Andreas Jaeger <aj@suse.de>, 1999.
4
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.
9
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.
14
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. */
19
7b0d235c 20#include <alloca.h>
591e1ffb
UD
21#include <argp.h>
22#include <dirent.h>
9c95d361 23#include <elf.h>
591e1ffb
UD
24#include <error.h>
25#include <errno.h>
5a35dfca 26#include <inttypes.h>
591e1ffb
UD
27#include <libintl.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <unistd.h>
32#include <sys/fcntl.h>
33#include <sys/mman.h>
34#include <sys/stat.h>
35#include <sys/types.h>
36
37#include "ldconfig.h"
45eca4d1 38#include "dl-cache.h"
591e1ffb 39
45eca4d1 40#include "dl-procinfo.h"
591e1ffb
UD
41
42#ifndef LD_SO_CONF
8ca91b36 43# define LD_SO_CONF SYSCONFDIR "/ld.so.conf"
591e1ffb
UD
44#endif
45
46/* Get libc version number. */
47#include <version.h>
48
49#define PACKAGE _libc_intl_domainname
50
591e1ffb
UD
51static const struct
52{
53 const char *name;
54 int flag;
a986484f 55} lib_types[] =
591e1ffb
UD
56{
57 {"libc4", FLAG_LIBC4},
58 {"libc5", FLAG_ELF_LIBC5},
59 {"libc6", FLAG_ELF_LIBC6},
60 {"glibc2", FLAG_ELF_LIBC6}
45eca4d1 61};
591e1ffb
UD
62
63
64/* List of directories to handle. */
65struct dir_entry
66{
67 char *path;
68 int flag;
4ceae915
AJ
69 ino64_t ino;
70 dev_t dev;
591e1ffb
UD
71 struct dir_entry *next;
72};
73
74/* The list is unsorted, contains no duplicates. Entries are added at
75 the end. */
76static struct dir_entry *dir_entries;
77
78/* Flags for different options. */
79/* Print Cache. */
80static int opt_print_cache = 0;
81
82/* Be verbose. */
83int opt_verbose = 0;
84
45eca4d1
UD
85/* Format to support. */
86/* 0: only libc5/glibc2; 1: both; 2: only glibc 2.2. */
87int opt_format = 1;
88
591e1ffb
UD
89/* Build cache. */
90static int opt_build_cache = 1;
91
92/* Generate links. */
93static int opt_link = 1;
94
95/* Only process directories specified on the command line. */
96static int opt_only_cline = 0;
97
98/* Path to root for chroot. */
99static char *opt_chroot;
100
b85697f6
UD
101/* Manually link given shared libraries. */
102static int opt_manual_link = 0;
103
591e1ffb 104/* Cache file to use. */
b4a555d6 105static char *cache_file;
591e1ffb
UD
106
107/* Configuration file. */
108static const char *config_file;
109
110/* Name and version of program. */
111static void print_version (FILE *stream, struct argp_state *state);
112void (*argp_program_version_hook) (FILE *, struct argp_state *)
113 = print_version;
114
115/* Definitions of arguments for argp functions. */
116static const struct argp_option options[] =
117{
118 { "print-cache", 'p', NULL, 0, N_("Print cache"), 0},
119 { "verbose", 'v', NULL, 0, N_("Generate verbose messages"), 0},
120 { NULL, 'N', NULL, 0, N_("Don't build cache"), 0},
121 { NULL, 'X', NULL, 0, N_("Don't generate links"), 0},
122 { NULL, 'r', "ROOT", 0, N_("Change to and use ROOT as root directory"), 0},
123 { NULL, 'C', "CACHE", 0, N_("Use CACHE as cache file"), 0},
124 { NULL, 'f', "CONF", 0, N_("Use CONF as configuration file"), 0},
125 { NULL, 'n', NULL, 0, N_("Only process directories specified on the command line. Don't build cache."), 0},
b85697f6 126 { NULL, 'l', NULL, 0, N_("Manually link individual libraries."), 0},
45eca4d1 127 { "format", 'c', "FORMAT", 0, N_("Format to use: new, old or compat (default)"), 0},
591e1ffb
UD
128 { NULL, 0, NULL, 0, NULL, 0 }
129};
130
131/* Short description of program. */
132static const char doc[] = N_("Configure Dynamic Linker Run Time Bindings.");
133
134/* Prototype for option handler. */
135static error_t parse_opt (int key, char *arg, struct argp_state *state);
136
137/* Data structure to communicate with argp functions. */
138static struct argp argp =
139{
140 options, parse_opt, NULL, doc, NULL, NULL, NULL
141};
142
a6c1c03a
AJ
143/* Check if string corresponds to an important hardware capability or
144 a platform. */
45eca4d1 145static int
a6c1c03a 146is_hwcap_platform (const char *name)
45eca4d1
UD
147{
148 int hwcap_idx = _dl_string_hwcap (name);
8ca91b36 149
45eca4d1
UD
150 if (hwcap_idx != -1 && ((1 << hwcap_idx) & HWCAP_IMPORTANT))
151 return 1;
a6c1c03a
AJ
152
153 hwcap_idx = _dl_string_platform (name);
154 if (hwcap_idx != -1)
155 return 1;
156
45eca4d1
UD
157 return 0;
158}
159
a6c1c03a
AJ
160/* Get hwcap (including platform) encoding of path. */
161static uint64_t
45eca4d1
UD
162path_hwcap (const char *path)
163{
164 char *str = xstrdup (path);
165 char *ptr;
a6c1c03a
AJ
166 uint64_t hwcap = 0;
167 uint64_t h;
45eca4d1
UD
168
169 size_t len;
170
171 len = strlen (str);
172 if (str[len] == '/')
173 str[len] = '\0';
174
175 /* Search pathname from the end and check for hwcap strings. */
176 for (;;)
177 {
178 ptr = strrchr (str, '/');
179
180 if (ptr == NULL)
181 break;
182
a6c1c03a 183 h = _dl_string_hwcap (ptr + 1);
45eca4d1 184
59553897
UD
185 if (h == (uint64_t) -1)
186 {
187 h = _dl_string_platform (ptr + 1);
188 if (h == (uint64_t) -1)
189 break;
190 }
a6c1c03a 191 hwcap += 1ULL << h;
591e1ffb 192
45eca4d1
UD
193 /* Search the next part of the path. */
194 *ptr = '\0';
195 }
196
197 free (str);
198 return hwcap;
199}
591e1ffb
UD
200
201/* Handle program arguments. */
202static error_t
203parse_opt (int key, char *arg, struct argp_state *state)
204{
205 switch (key)
206 {
207 case 'C':
208 cache_file = arg;
209 break;
210 case 'f':
211 config_file = arg;
212 break;
b85697f6
UD
213 case 'l':
214 opt_manual_link = 1;
215 break;
591e1ffb
UD
216 case 'N':
217 opt_build_cache = 0;
218 break;
219 case 'n':
220 opt_build_cache = 0;
221 opt_only_cline = 1;
222 break;
223 case 'p':
224 opt_print_cache = 1;
225 break;
226 case 'r':
227 opt_chroot = arg;
228 break;
229 case 'v':
230 opt_verbose = 1;
231 break;
232 case 'X':
233 opt_link = 0;
234 break;
45eca4d1
UD
235 case 'c':
236 if (strcmp (arg, "old") == 0)
237 opt_format = 0;
238 else if (strcmp (arg, "compat") == 0)
239 opt_format = 1;
240 else if (strcmp (arg, "new") == 0)
241 opt_format = 2;
242 break;
591e1ffb
UD
243 default:
244 return ARGP_ERR_UNKNOWN;
245 }
246
247 return 0;
248}
249
250/* Print the version information. */
251static void
252print_version (FILE *stream, struct argp_state *state)
253{
254 fprintf (stream, "ldconfig (GNU %s) %s\n", PACKAGE, VERSION);
255 fprintf (stream, gettext ("\
256Copyright (C) %s Free Software Foundation, Inc.\n\
257This is free software; see the source for copying conditions. There is NO\n\
258warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
06a60d9c 259"), "2001");
591e1ffb
UD
260 fprintf (stream, gettext ("Written by %s.\n"),
261 "Andreas Jaeger");
262}
263
a8fd59b0
AJ
264/* Add a single directory entry. */
265static void
266add_single_dir (struct dir_entry *entry, int verbose)
267{
268 struct dir_entry *ptr, *prev;
269
270 ptr = dir_entries;
271 prev = ptr;
272 while (ptr != NULL)
273 {
274 /* Check for duplicates. */
4ceae915 275 if (ptr->ino == entry->ino && ptr->dev == entry->dev)
a8fd59b0
AJ
276 {
277 if (opt_verbose && verbose)
278 error (0, 0, _("Path `%s' given more than once"), entry->path);
279 /* Use the newer information. */
280 ptr->flag = entry->flag;
4ceae915 281 free (entry->path);
a8fd59b0
AJ
282 free (entry);
283 break;
284 }
285 prev = ptr;
286 ptr = ptr->next;
287 }
288 /* Is this the first entry? */
289 if (ptr == NULL && dir_entries == NULL)
290 dir_entries = entry;
291 else if (ptr == NULL)
292 prev->next = entry;
293}
294
591e1ffb
UD
295/* Add one directory to the list of directories to process. */
296static void
297add_dir (const char *line)
298{
299 char *equal_sign;
a8fd59b0 300 struct dir_entry *entry;
591e1ffb 301 unsigned int i;
4ceae915 302 struct stat64 stat_buf;
45eca4d1 303
591e1ffb
UD
304 entry = xmalloc (sizeof (struct dir_entry));
305 entry->next = NULL;
45eca4d1 306
591e1ffb
UD
307 /* Search for an '=' sign. */
308 entry->path = xstrdup (line);
309 equal_sign = strchr (entry->path, '=');
310 if (equal_sign)
311 {
312 *equal_sign = '\0';
313 ++equal_sign;
314 entry->flag = FLAG_ANY;
a986484f 315 for (i = 0; i < sizeof (lib_types) / sizeof (lib_types[0]); ++i)
591e1ffb
UD
316 if (strcmp (equal_sign, lib_types[i].name) == 0)
317 {
318 entry->flag = lib_types[i].flag;
319 break;
320 }
321 if (entry->flag == FLAG_ANY)
322 error (0, 0, _("%s is not a known library type"), equal_sign);
323 }
324 else
325 {
326 entry->flag = FLAG_ANY;
327 }
328
329 /* Canonify path: for now only remove trailing slashes. */
330 i = strlen (entry->path) - 1;
331 while (entry->path[i] == '/' && i > 0)
332 {
a986484f 333 entry->path[i] = '\0';
591e1ffb
UD
334 --i;
335 }
45eca4d1 336
4ceae915
AJ
337 if (stat64 (entry->path, &stat_buf))
338 {
8645ad47
AJ
339 if (opt_verbose)
340 error (0, errno, _("Can't stat %s"), entry->path);
4ceae915
AJ
341 free (entry->path);
342 free (entry);
343 return;
344 }
345
346 entry->ino = stat_buf.st_ino;
347 entry->dev = stat_buf.st_dev;
348
349 add_single_dir (entry, 1);
591e1ffb
UD
350}
351
352
b4a555d6
UD
353static int
354chroot_stat (const char *real_path, const char *path, struct stat64 *st)
355{
356 int ret;
357 char *canon_path;
358
359 if (!opt_chroot)
360 return stat64 (real_path, st);
361
362 ret = lstat64 (real_path, st);
363 if (ret || !S_ISLNK (st->st_mode))
364 return ret;
365
366 canon_path = chroot_canon (opt_chroot, path);
367 if (canon_path == NULL)
368 return -1;
369
370 ret = stat64 (canon_path, st);
371 free (canon_path);
372 return ret;
373}
374
591e1ffb
UD
375/* Create a symbolic link from soname to libname in directory path. */
376static void
b4a555d6
UD
377create_links (const char *real_path, const char *path, const char *libname,
378 const char *soname)
591e1ffb 379{
7b0d235c 380 char *full_libname, *full_soname;
b4a555d6
UD
381 char *real_full_libname, *real_full_soname;
382 struct stat64 stat_lib, stat_so, lstat_so;
591e1ffb
UD
383 int do_link = 1;
384 int do_remove = 1;
385 /* XXX: The logics in this function should be simplified. */
45eca4d1 386
591e1ffb 387 /* Get complete path. */
7b0d235c 388 full_libname = alloca (strlen (path) + strlen (libname) + 2);
7c545dbe 389 full_soname = alloca (strlen (path) + strlen (soname) + 2);
7b0d235c
AJ
390 sprintf (full_libname, "%s/%s", path, libname);
391 sprintf (full_soname, "%s/%s", path, soname);
b4a555d6
UD
392 if (opt_chroot)
393 {
394 real_full_libname = alloca (strlen (real_path) + strlen (libname) + 2);
7c545dbe 395 real_full_soname = alloca (strlen (real_path) + strlen (soname) + 2);
b4a555d6
UD
396 sprintf (real_full_libname, "%s/%s", real_path, libname);
397 sprintf (real_full_soname, "%s/%s", real_path, soname);
398 }
399 else
400 {
401 real_full_libname = full_libname;
402 real_full_soname = full_soname;
403 }
591e1ffb
UD
404
405 /* Does soname already exist and point to the right library? */
b4a555d6 406 if (chroot_stat (real_full_soname, full_soname, &stat_so) == 0)
591e1ffb 407 {
b4a555d6 408 if (chroot_stat (real_full_libname, full_libname, &stat_lib))
591e1ffb
UD
409 {
410 error (0, 0, _("Can't stat %s\n"), full_libname);
411 return;
412 }
413 if (stat_lib.st_dev == stat_so.st_dev
414 && stat_lib.st_ino == stat_so.st_ino)
415 /* Link is already correct. */
416 do_link = 0;
b4a555d6 417 else if (lstat64 (full_soname, &lstat_so) == 0
591e1ffb
UD
418 && !S_ISLNK (lstat_so.st_mode))
419 {
420 error (0, 0, _("%s is not a symbolic link\n"), full_soname);
421 do_link = 0;
422 do_remove = 0;
423 }
424 }
b4a555d6 425 else if (lstat64 (real_full_soname, &lstat_so) != 0
591e1ffb
UD
426 || !S_ISLNK (lstat_so.st_mode))
427 /* Unless it is a stale symlink, there is no need to remove. */
428 do_remove = 0;
429
430 if (opt_verbose)
431 printf ("\t%s -> %s", soname, libname);
432
433 if (do_link && opt_link)
434 {
435 /* Remove old link. */
436 if (do_remove)
b4a555d6 437 if (unlink (real_full_soname))
591e1ffb
UD
438 {
439 error (0, 0, _("Can't unlink %s"), full_soname);
440 do_link = 0;
441 }
442 /* Create symbolic link. */
b4a555d6 443 if (do_link && symlink (libname, real_full_soname))
591e1ffb
UD
444 {
445 error (0, 0, _("Can't link %s to %s"), full_soname, libname);
446 do_link = 0;
447 }
448 if (opt_verbose)
449 {
450 if (do_link)
451 fputs (_(" (changed)\n"), stdout);
452 else
453 fputs (_(" (SKIPPED)\n"), stdout);
454 }
455 }
456 else if (opt_verbose)
457 fputs ("\n", stdout);
458}
459
b85697f6
UD
460/* Manually link the given library. */
461static void
462manual_link (char *library)
463{
464 char *path;
b4a555d6
UD
465 char *real_path;
466 char *real_library;
b85697f6
UD
467 char *libname;
468 char *soname;
b4a555d6 469 struct stat64 stat_buf;
b85697f6 470 int flag;
a986484f 471 unsigned int osversion;
b85697f6
UD
472
473 /* Prepare arguments for create_links call. Split library name in
474 directory and filename first. Since path is allocated, we've got
475 to be careful to free at the end. */
476 path = xstrdup (library);
477 libname = strrchr (path, '/');
478
479 if (libname)
480 {
481 /* Successfully split names. Check if path is just "/" to avoid
482 an empty path. */
483 if (libname == path)
484 {
485 libname = library + 1;
486 path = xrealloc (path, 2);
487 strcpy (path, "/");
488 }
489 else
490 {
491 *libname = '\0';
492 ++libname;
493 }
494 }
495 else
496 {
497 /* There's no path, construct one. */
498 libname = library;
499 path = xrealloc (path, 2);
500 strcpy (path, ".");
501 }
502
b4a555d6
UD
503 if (opt_chroot)
504 {
505 real_path = chroot_canon (opt_chroot, path);
506 if (real_path == NULL)
507 {
508 error (0, errno, _("Can't find %s"), path);
509 free (path);
510 return;
511 }
512 real_library = alloca (strlen (real_path) + strlen (libname) + 2);
513 sprintf (real_library, "%s/%s", real_path, libname);
514 }
515 else
516 {
517 real_path = path;
518 real_library = library;
519 }
520
b85697f6 521 /* Do some sanity checks first. */
b4a555d6 522 if (lstat64 (real_library, &stat_buf))
b85697f6
UD
523 {
524 error (0, errno, _("Can't lstat %s"), library);
525 free (path);
526 return;
527 }
528 /* We don't want links here! */
529 else if (!S_ISREG (stat_buf.st_mode))
530 {
531 error (0, 0, _("Ignored file %s since it is not a regular file."),
532 library);
533 free (path);
534 return;
535 }
a986484f
UD
536 if (process_file (real_library, library, libname, &flag, &osversion,
537 &soname, 0))
b85697f6
UD
538 {
539 error (0, 0, _("No link created since soname could not be found for %s"),
540 library);
541 free (path);
542 return;
543 }
b4a555d6 544 create_links (real_path, path, libname, soname);
b85697f6
UD
545 free (soname);
546 free (path);
547}
548
549
591e1ffb
UD
550/* Read a whole directory and search for libraries.
551 The purpose is two-fold:
552 - search for libraries which will be added to the cache
553 - create symbolic links to the soname for each library
554
555 This has to be done separatly for each directory.
45eca4d1 556
591e1ffb
UD
557 To keep track of which libraries to add to the cache and which
558 links to create, we save a list of all libraries.
559
560 The algorithm is basically:
561 for all libraries in the directory do
562 get soname of library
563 if soname is already in list
564 if new library is newer, replace entry
565 otherwise ignore this library
566 otherwise add library to list
45eca4d1 567
591e1ffb
UD
568 For example, if the two libraries libxy.so.1.1 and libxy.so.1.2
569 exist and both have the same soname, e.g. libxy.so, a symbolic link
570 is created from libxy.so.1.2 (the newer one) to libxy.so.
571 libxy.so.1.2 and libxy.so are added to the cache - but not
572 libxy.so.1.1. */
573
574/* Information for one library. */
45eca4d1 575struct dlib_entry
591e1ffb
UD
576{
577 char *name;
578 char *soname;
579 int flag;
580 int is_link;
a986484f 581 unsigned int osversion;
591e1ffb
UD
582 struct dlib_entry *next;
583};
584
585
586static void
587search_dir (const struct dir_entry *entry)
588{
589 DIR *dir;
590 struct dirent *direntry;
b4a555d6
UD
591 char *file_name, *dir_name, *real_file_name, *real_name;
592 int file_name_len, real_file_name_len, len;
591e1ffb
UD
593 char *soname;
594 struct dlib_entry *dlibs;
595 struct dlib_entry *dlib_ptr;
4ceae915
AJ
596 struct stat64 lstat_buf, stat_buf;
597 int is_link, is_dir;
a6c1c03a 598 uint64_t hwcap = path_hwcap (entry->path);
a986484f 599 unsigned int osversion;
45eca4d1 600
7b0d235c
AJ
601 file_name_len = PATH_MAX;
602 file_name = alloca (file_name_len);
f0189a54 603
591e1ffb
UD
604 dlibs = NULL;
605
606 if (opt_verbose)
45eca4d1
UD
607 {
608 if (hwcap != 0)
5a35dfca 609 printf ("%s: (hwcap: 0x%" PRIx64 ")\n", entry->path, hwcap);
45eca4d1
UD
610 else
611 printf ("%s:\n", entry->path);
612 }
613
b4a555d6
UD
614 if (opt_chroot)
615 {
616 dir_name = chroot_canon (opt_chroot, entry->path);
617 real_file_name_len = PATH_MAX;
618 real_file_name = alloca (real_file_name_len);
619 }
620 else
621 {
622 dir_name = entry->path;
623 real_file_name_len = 0;
624 real_file_name = file_name;
625 }
626
627 if (dir_name == NULL || (dir = opendir (dir_name)) == NULL)
591e1ffb
UD
628 {
629 if (opt_verbose)
630 error (0, errno, _("Can't open directory %s"), entry->path);
b4a555d6
UD
631 if (opt_chroot && dir_name)
632 free (dir_name);
591e1ffb
UD
633 return;
634 }
45eca4d1 635
591e1ffb
UD
636 while ((direntry = readdir (dir)) != NULL)
637 {
638 int flag;
639#ifdef _DIRENT_HAVE_D_TYPE
640 /* We only look at links and regular files. */
641 if (direntry->d_type != DT_UNKNOWN
642 && direntry->d_type != DT_LNK
45eca4d1
UD
643 && direntry->d_type != DT_REG
644 && direntry->d_type != DT_DIR)
591e1ffb
UD
645 continue;
646#endif /* _DIRENT_HAVE_D_TYPE */
45eca4d1
UD
647 /* Does this file look like a shared library or is it a hwcap
648 subdirectory? The dynamic linker is also considered as
649 shared library. */
650 if (((strncmp (direntry->d_name, "lib", 3) != 0
651 && strncmp (direntry->d_name, "ld-", 3) != 0)
652 || strstr (direntry->d_name, ".so") == NULL)
a6c1c03a 653 && !is_hwcap_platform (direntry->d_name))
591e1ffb 654 continue;
7b0d235c
AJ
655 len = strlen (entry->path) + strlen (direntry->d_name);
656 if (len > file_name_len)
591e1ffb 657 {
7b0d235c
AJ
658 file_name_len = len + 1;
659 file_name = alloca (file_name_len);
b4a555d6
UD
660 if (!opt_chroot)
661 real_file_name = file_name;
662 }
663 sprintf (file_name, "%s/%s", entry->path, direntry->d_name);
664 if (opt_chroot)
665 {
666 len = strlen (dir_name) + strlen (direntry->d_name);
667 if (len > real_file_name_len)
668 {
669 real_file_name_len = len + 1;
670 real_file_name = alloca (real_file_name_len);
671 }
672 sprintf (real_file_name, "%s/%s", dir_name, direntry->d_name);
591e1ffb 673 }
7c3002f0
UD
674#ifdef _DIRENT_HAVE_D_TYPE
675 if (direntry->d_type != DT_UNKNOWN)
4ceae915 676 lstat_buf.st_mode = DTTOIF (direntry->d_type);
7c3002f0
UD
677 else
678#endif
4ceae915 679 if (lstat64 (real_file_name, &lstat_buf))
7c3002f0 680 {
7b0d235c 681 error (0, errno, _("Can't lstat %s"), file_name);
7c3002f0
UD
682 continue;
683 }
684
4ceae915
AJ
685 is_link = S_ISLNK (lstat_buf.st_mode);
686 if (is_link)
687 {
688 /* In case of symlink, we check if the symlink refers to
689 a directory. */
690 if (stat64 (real_file_name, &stat_buf))
691 {
8645ad47
AJ
692 if (opt_verbose)
693 error (0, errno, _("Can't stat %s"), file_name);
4ceae915
AJ
694 continue;
695 }
696 is_dir = S_ISDIR (stat_buf.st_mode);
697 }
698 else
699 is_dir = S_ISDIR (lstat_buf.st_mode);
700
701 if (is_dir && is_hwcap_platform (direntry->d_name))
45eca4d1 702 {
a8fd59b0
AJ
703 /* Handle subdirectory later. */
704 struct dir_entry *new_entry;
705
706 new_entry = xmalloc (sizeof (struct dir_entry));
7b0d235c 707 new_entry->path = xstrdup (file_name);
a8fd59b0
AJ
708 new_entry->flag = entry->flag;
709 new_entry->next = NULL;
4ceae915
AJ
710 if (is_link)
711 {
712 new_entry->ino = stat_buf.st_ino;
713 new_entry->dev = stat_buf.st_dev;
714 }
715 else
716 {
717 new_entry->ino = lstat_buf.st_ino;
718 new_entry->dev = lstat_buf.st_dev;
719 }
a8fd59b0 720 add_single_dir (new_entry, 0);
45eca4d1
UD
721 continue;
722 }
4ceae915 723 else if (!S_ISREG (stat_buf.st_mode) && !is_link)
591e1ffb
UD
724 continue;
725
b4a555d6
UD
726 if (opt_chroot && is_link)
727 {
728 real_name = chroot_canon (opt_chroot, file_name);
729 if (real_name == NULL)
730 {
731 if (strstr (file_name, ".so") == NULL)
732 error (0, 0, _("Input file %s not found.\n"), file_name);
733 continue;
734 }
735 }
736 else
737 real_name = real_file_name;
591e1ffb 738
b4a555d6 739 if (process_file (real_name, file_name, direntry->d_name, &flag,
a986484f 740 &osversion, &soname, is_link))
b4a555d6
UD
741 {
742 if (real_name != real_file_name)
743 free (real_name);
744 continue;
745 }
746
747 if (real_name != real_file_name)
748 free (real_name);
591e1ffb
UD
749
750 /* Links will just point to itself. */
751 if (is_link)
752 {
753 free (soname);
754 soname = xstrdup (direntry->d_name);
755 }
45eca4d1 756
591e1ffb
UD
757 if (flag == FLAG_ELF
758 && (entry->flag == FLAG_ELF_LIBC5
759 || entry->flag == FLAG_ELF_LIBC6))
760 flag = entry->flag;
761 /* Some sanity checks to print warnings. */
762 if (opt_verbose)
763 {
764 if (flag == FLAG_ELF_LIBC5 && entry->flag != FLAG_ELF_LIBC5
765 && entry->flag != FLAG_ANY)
7b0d235c 766 error (0, 0, _("libc5 library %s in wrong directory"), file_name);
591e1ffb
UD
767 if (flag == FLAG_ELF_LIBC6 && entry->flag != FLAG_ELF_LIBC6
768 && entry->flag != FLAG_ANY)
7b0d235c 769 error (0, 0, _("libc6 library %s in wrong directory"), file_name);
591e1ffb
UD
770 if (flag == FLAG_LIBC4 && entry->flag != FLAG_LIBC4
771 && entry->flag != FLAG_ANY)
7b0d235c 772 error (0, 0, _("libc4 library %s in wrong directory"), file_name);
591e1ffb 773 }
45eca4d1 774
591e1ffb
UD
775 /* Add library to list. */
776 for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next)
777 {
778 /* Is soname already in list? */
779 if (strcmp (dlib_ptr->soname, soname) == 0)
780 {
781 /* Prefer a file to a link, otherwise check which one
782 is newer. */
783 if ((!is_link && dlib_ptr->is_link)
784 || (is_link == dlib_ptr->is_link
45eca4d1 785 && _dl_cache_libcmp (dlib_ptr->name, direntry->d_name) < 0))
591e1ffb
UD
786 {
787 /* It's newer - add it. */
788 /* Flag should be the same - sanity check. */
789 if (dlib_ptr->flag != flag)
790 {
791 if (dlib_ptr->flag == FLAG_ELF
792 && (flag == FLAG_ELF_LIBC5 || flag == FLAG_ELF_LIBC6))
793 dlib_ptr->flag = flag;
794 else if ((dlib_ptr->flag == FLAG_ELF_LIBC5
795 || dlib_ptr->flag == FLAG_ELF_LIBC6)
796 && flag == FLAG_ELF)
797 dlib_ptr->flag = flag;
798 else
799 error (0, 0, _("libraries %s and %s in directory %s have same soname but different type."),
800 dlib_ptr->name, direntry->d_name, entry->path);
801 }
802 free (dlib_ptr->name);
b15ff9d6 803 dlib_ptr->osversion = osversion;
591e1ffb
UD
804 dlib_ptr->name = xstrdup (direntry->d_name);
805 dlib_ptr->is_link = is_link;
806 }
807 /* Don't add this library, abort loop. */
808 /* Also free soname, since it's dynamically allocated. */
809 free (soname);
810 break;
811 }
812 }
813 /* Add the library if it's not already in. */
814 if (dlib_ptr == NULL)
815 {
816 dlib_ptr = (struct dlib_entry *)xmalloc (sizeof (struct dlib_entry));
817 dlib_ptr->name = xstrdup (direntry->d_name);
818 dlib_ptr->flag = flag;
a986484f 819 dlib_ptr->osversion = osversion;
591e1ffb
UD
820 dlib_ptr->soname = soname;
821 dlib_ptr->is_link = is_link;
822 /* Add at head of list. */
823 dlib_ptr->next = dlibs;
824 dlibs = dlib_ptr;
825 }
826 }
827
828 closedir (dir);
829
830 /* Now dlibs contains a list of all libs - add those to the cache
831 and created all symbolic links. */
832 for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next)
833 {
834 /* Don't create links to links. */
835 if (dlib_ptr->is_link == 0)
b4a555d6
UD
836 create_links (dir_name, entry->path, dlib_ptr->name,
837 dlib_ptr->soname);
591e1ffb 838 if (opt_build_cache)
a986484f
UD
839 add_to_cache (entry->path, dlib_ptr->soname, dlib_ptr->flag,
840 dlib_ptr->osversion, hwcap);
591e1ffb
UD
841 }
842
843 /* Free all resources. */
45eca4d1 844 while (dlibs)
591e1ffb
UD
845 {
846 dlib_ptr = dlibs;
847 free (dlib_ptr->soname);
848 free (dlib_ptr->name);
849 dlibs = dlibs->next;
850 free (dlib_ptr);
851 }
b4a555d6
UD
852
853 if (opt_chroot && dir_name)
854 free (dir_name);
591e1ffb
UD
855}
856
857/* Search through all libraries. */
858static void
859search_dirs (void)
860{
861 struct dir_entry *entry;
862
863 for (entry = dir_entries; entry != NULL; entry = entry->next)
864 search_dir (entry);
865
866 /* Free all allocated memory. */
867 while (dir_entries)
868 {
869 entry = dir_entries;
870 dir_entries = dir_entries->next;
871 free (entry->path);
872 free (entry);
873 }
874}
875
876
877/* Parse configuration file. */
878static void
879parse_conf (const char *filename)
880{
b4a555d6 881 FILE *file = NULL;
591e1ffb 882 char *line = NULL;
b4a555d6 883 const char *canon;
591e1ffb 884 size_t len = 0;
45eca4d1 885
b4a555d6
UD
886 if (opt_chroot)
887 {
888 canon = chroot_canon (opt_chroot, filename);
889 if (canon)
890 file = fopen (canon, "r");
891 else
892 canon = filename;
893 }
894 else
895 {
896 canon = filename;
897 file = fopen (filename, "r");
898 }
591e1ffb
UD
899
900 if (file == NULL)
901 {
b4a555d6
UD
902 error (0, errno, _("Can't open configuration file %s"), canon);
903 if (canon != filename)
904 free ((char *) canon);
591e1ffb
UD
905 return;
906 }
907
b4a555d6
UD
908 if (canon != filename)
909 free ((char *) canon);
910
591e1ffb
UD
911 do
912 {
913 ssize_t n = getline (&line, &len, file);
914 if (n < 0)
915 break;
916
917 if (line[n - 1] == '\n')
918 line[n - 1] = '\0';
919
920 /* Because the file format does not know any form of quoting we
921 can search forward for the next '#' character and if found
922 make it terminating the line. */
923 *strchrnul (line, '#') = '\0';
924
925 /* If the line is blank it is ignored. */
926 if (line[0] == '\0')
927 continue;
928
929 add_dir (line);
930 } while (!feof (file));
931
932 /* Free buffer and close file. */
933 free (line);
934 fclose (file);
935}
936
937
938int
939main (int argc, char **argv)
940{
941 int remaining;
45eca4d1 942
591e1ffb
UD
943 /* Parse and process arguments. */
944 argp_parse (&argp, argc, argv, 0, &remaining, NULL);
945
b85697f6
UD
946 /* Remaining arguments are additional libraries if opt_manual_link
947 is not set. */
948 if (remaining != argc && !opt_manual_link)
591e1ffb
UD
949 {
950 int i;
951 for (i = remaining; i < argc; ++i)
a986484f 952 add_dir (argv[i]);
591e1ffb
UD
953 }
954
591e1ffb
UD
955 if (opt_chroot)
956 {
f0189a54
UD
957 /* Normalize the path a bit, we might need it for printing later. */
958 char *endp = strchr (opt_chroot, '\0');
b4a555d6 959 while (endp > opt_chroot && endp[-1] == '/')
f0189a54
UD
960 --endp;
961 *endp = '\0';
b4a555d6
UD
962 if (endp == opt_chroot)
963 opt_chroot = NULL;
f0189a54 964
b4a555d6
UD
965 if (opt_chroot)
966 {
967 /* It is faster to use chroot if we can. */
968 if (!chroot (opt_chroot))
969 {
970 if (chdir ("/"))
971 error (EXIT_FAILURE, errno, _("Can't chdir to /"));
972 opt_chroot = NULL;
973 }
974 }
975 }
976
977 if (cache_file == NULL)
978 {
979 cache_file = alloca (strlen (LD_SO_CACHE) + 1);
980 strcpy (cache_file, LD_SO_CACHE);
591e1ffb
UD
981 }
982
b4a555d6
UD
983 if (config_file == NULL)
984 config_file = LD_SO_CONF;
985
591e1ffb
UD
986 if (opt_print_cache)
987 {
b4a555d6
UD
988 if (opt_chroot)
989 {
990 char *p = chroot_canon (opt_chroot, cache_file);
991 if (p == NULL)
992 error (EXIT_FAILURE, errno, _("Can't open cache file %s\n"),
993 cache_file);
994 cache_file = p;
995 }
591e1ffb 996 print_cache (cache_file);
b4a555d6
UD
997 if (opt_chroot)
998 free (cache_file);
591e1ffb
UD
999 exit (0);
1000 }
1001
b4a555d6
UD
1002 if (opt_chroot)
1003 {
1004 /* Canonicalize the directory name of cache_file, not cache_file,
1005 because we'll rename a temporary cache file to it. */
1006 char *p = strrchr (cache_file, '/');
1007 char *canon = chroot_canon (opt_chroot,
1008 p ? (*p = '\0', cache_file) : "/");
1009
1010 if (canon == NULL)
1011 {
1012 error (EXIT_FAILURE, errno,
1013 _("Can't open cache file directory %s\n"),
1014 p ? cache_file : "/");
1015 }
1016
1017 if (p)
1018 ++p;
1019 else
1020 p = cache_file;
1021
1022 cache_file = alloca (strlen (canon) + strlen (p) + 2);
1023 sprintf (cache_file, "%s/%s", canon, p);
1024 free (canon);
1025 }
1026
b85697f6
UD
1027 if (opt_manual_link)
1028 {
1029 /* Link all given libraries manually. */
1030 int i;
1031
1032 for (i = remaining; i < argc; ++i)
a986484f 1033 manual_link (argv[i]);
b85697f6
UD
1034
1035 exit (0);
1036 }
45eca4d1
UD
1037
1038
591e1ffb
UD
1039 if (opt_build_cache)
1040 init_cache ();
1041
1042 if (!opt_only_cline)
1043 {
1044 /* Always add the standard search paths. */
8ca91b36
UD
1045 add_dir (SLIBDIR);
1046 if (strcmp (SLIBDIR, LIBDIR))
1047 add_dir (LIBDIR);
591e1ffb
UD
1048
1049 parse_conf (config_file);
1050 }
45eca4d1 1051
591e1ffb
UD
1052 search_dirs ();
1053
1054 if (opt_build_cache)
1055 save_cache (cache_file);
1056
1057 return 0;
1058}