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