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