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