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