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