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