Back to index

glibc  2.9
ldconfig.c
Go to the documentation of this file.
00001 /* Copyright (C) 1999-2007, 2008 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Contributed by Andreas Jaeger <aj@suse.de>, 1999.
00004 
00005    This program is free software; you can redistribute it and/or modify
00006    it under the terms of the GNU General Public License as published
00007    by the Free Software Foundation; version 2 of the License, or
00008    (at your option) any later version.
00009 
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013    GNU General Public License for more details.
00014 
00015    You should have received a copy of the GNU General Public License
00016    along with this program; if not, write to the Free Software Foundation,
00017    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
00018 
00019 #define PROCINFO_CLASS static
00020 #include <alloca.h>
00021 #include <argp.h>
00022 #include <dirent.h>
00023 #include <elf.h>
00024 #include <error.h>
00025 #include <errno.h>
00026 #include <inttypes.h>
00027 #include <libintl.h>
00028 #include <locale.h>
00029 #include <stdbool.h>
00030 #include <stdio.h>
00031 #include <stdio_ext.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034 #include <unistd.h>
00035 #include <sys/fcntl.h>
00036 #include <sys/mman.h>
00037 #include <sys/stat.h>
00038 #include <sys/types.h>
00039 #include <glob.h>
00040 #include <libgen.h>
00041 
00042 #include <ldconfig.h>
00043 #include <dl-cache.h>
00044 
00045 #include <dl-procinfo.h>
00046 
00047 #ifdef _DL_FIRST_PLATFORM
00048 # define _DL_FIRST_EXTRA (_DL_FIRST_PLATFORM + _DL_PLATFORMS_COUNT)
00049 #else
00050 # define _DL_FIRST_EXTRA _DL_HWCAP_COUNT
00051 #endif
00052 
00053 #ifndef LD_SO_CONF
00054 # define LD_SO_CONF SYSCONFDIR "/ld.so.conf"
00055 #endif
00056 
00057 /* Get libc version number.  */
00058 #include <version.h>
00059 
00060 #define PACKAGE _libc_intl_domainname
00061 
00062 static const struct
00063 {
00064   const char *name;
00065   int flag;
00066 } lib_types[] =
00067 {
00068   {"libc4", FLAG_LIBC4},
00069   {"libc5", FLAG_ELF_LIBC5},
00070   {"libc6", FLAG_ELF_LIBC6},
00071   {"glibc2", FLAG_ELF_LIBC6}
00072 };
00073 
00074 
00075 /* List of directories to handle.  */
00076 struct dir_entry
00077 {
00078   char *path;
00079   int flag;
00080   ino64_t ino;
00081   dev_t dev;
00082   struct dir_entry *next;
00083 };
00084 
00085 /* The list is unsorted, contains no duplicates.  Entries are added at
00086    the end.  */
00087 static struct dir_entry *dir_entries;
00088 
00089 /* Flags for different options.  */
00090 /* Print Cache.  */
00091 static int opt_print_cache;
00092 
00093 /* Be verbose.  */
00094 int opt_verbose;
00095 
00096 /* Format to support.  */
00097 /* 0: only libc5/glibc2; 1: both; 2: only glibc 2.2.  */
00098 int opt_format = 1;
00099 
00100 /* Build cache.  */
00101 static int opt_build_cache = 1;
00102 
00103 /* Generate links.  */
00104 static int opt_link = 1;
00105 
00106 /* Only process directories specified on the command line.  */
00107 static int opt_only_cline;
00108 
00109 /* Path to root for chroot.  */
00110 static char *opt_chroot;
00111 
00112 /* Manually link given shared libraries.  */
00113 static int opt_manual_link;
00114 
00115 /* Should we ignore an old auxiliary cache file?  */
00116 static int opt_ignore_aux_cache;
00117 
00118 /* Cache file to use.  */
00119 static char *cache_file;
00120 
00121 /* Configuration file.  */
00122 static const char *config_file;
00123 
00124 /* Mask to use for important hardware capabilities.  */
00125 static unsigned long int hwcap_mask = HWCAP_IMPORTANT;
00126 
00127 /* Configuration-defined capabilities defined in kernel vDSOs.  */
00128 static const char *hwcap_extra[64 - _DL_FIRST_EXTRA];
00129 
00130 /* Name and version of program.  */
00131 static void print_version (FILE *stream, struct argp_state *state);
00132 void (*argp_program_version_hook) (FILE *, struct argp_state *)
00133      = print_version;
00134 
00135 /* Definitions of arguments for argp functions.  */
00136 static const struct argp_option options[] =
00137 {
00138   { "print-cache", 'p', NULL, 0, N_("Print cache"), 0},
00139   { "verbose", 'v', NULL, 0, N_("Generate verbose messages"), 0},
00140   { NULL, 'N', NULL, 0, N_("Don't build cache"), 0},
00141   { NULL, 'X', NULL, 0, N_("Don't generate links"), 0},
00142   { NULL, 'r', N_("ROOT"), 0, N_("Change to and use ROOT as root directory"), 0},
00143   { NULL, 'C', N_("CACHE"), 0, N_("Use CACHE as cache file"), 0},
00144   { NULL, 'f', N_("CONF"), 0, N_("Use CONF as configuration file"), 0},
00145   { NULL, 'n', NULL, 0, N_("Only process directories specified on the command line.  Don't build cache."), 0},
00146   { NULL, 'l', NULL, 0, N_("Manually link individual libraries."), 0},
00147   { "format", 'c', N_("FORMAT"), 0, N_("Format to use: new, old or compat (default)"), 0},
00148   { "ignore-aux-cache", 'i', NULL, 0, N_("Ignore auxiliary cache file"), 0},
00149   { NULL, 0, NULL, 0, NULL, 0 }
00150 };
00151 
00152 #define PROCINFO_CLASS static
00153 #include <dl-procinfo.c>
00154 
00155 /* Short description of program.  */
00156 static const char doc[] = N_("Configure Dynamic Linker Run Time Bindings.");
00157 
00158 /* Prototype for option handler.  */
00159 static error_t parse_opt (int key, char *arg, struct argp_state *state);
00160 
00161 /* Data structure to communicate with argp functions.  */
00162 static struct argp argp =
00163 {
00164   options, parse_opt, NULL, doc, NULL, NULL, NULL
00165 };
00166 
00167 /* Check if string corresponds to an important hardware capability or
00168    a platform.  */
00169 static int
00170 is_hwcap_platform (const char *name)
00171 {
00172   int hwcap_idx = _dl_string_hwcap (name);
00173 
00174   if (hwcap_idx != -1 && ((1 << hwcap_idx) & hwcap_mask))
00175     return 1;
00176 
00177   hwcap_idx = _dl_string_platform (name);
00178   if (hwcap_idx != -1)
00179     return 1;
00180 
00181   for (hwcap_idx = _DL_FIRST_EXTRA; hwcap_idx < 64; ++hwcap_idx)
00182     if (hwcap_extra[hwcap_idx - _DL_FIRST_EXTRA] != NULL
00183        && !strcmp (name, hwcap_extra[hwcap_idx - _DL_FIRST_EXTRA]))
00184       return 1;
00185 
00186   return 0;
00187 }
00188 
00189 /* Get hwcap (including platform) encoding of path.  */
00190 static uint64_t
00191 path_hwcap (const char *path)
00192 {
00193   char *str = xstrdup (path);
00194   char *ptr;
00195   uint64_t hwcap = 0;
00196   uint64_t h;
00197 
00198   size_t len;
00199 
00200   len = strlen (str);
00201   if (str[len] == '/')
00202     str[len] = '\0';
00203 
00204   /* Search pathname from the end and check for hwcap strings.  */
00205   for (;;)
00206     {
00207       ptr = strrchr (str, '/');
00208 
00209       if (ptr == NULL)
00210        break;
00211 
00212       h = _dl_string_hwcap (ptr + 1);
00213 
00214       if (h == (uint64_t) -1)
00215        {
00216          h = _dl_string_platform (ptr + 1);
00217          if (h == (uint64_t) -1)
00218            {
00219              for (h = _DL_FIRST_EXTRA; h < 64; ++h)
00220               if (hwcap_extra[h - _DL_FIRST_EXTRA] != NULL
00221                   && !strcmp (ptr + 1, hwcap_extra[h - _DL_FIRST_EXTRA]))
00222                 break;
00223              if (h == 64)
00224               break;
00225            }
00226        }
00227       hwcap += 1ULL << h;
00228 
00229       /* Search the next part of the path.  */
00230       *ptr = '\0';
00231     }
00232 
00233   free (str);
00234   return hwcap;
00235 }
00236 
00237 /* Handle program arguments.  */
00238 static error_t
00239 parse_opt (int key, char *arg, struct argp_state *state)
00240 {
00241   switch (key)
00242     {
00243     case 'C':
00244       cache_file = arg;
00245       /* Ignore auxiliary cache since we use non-standard cache.  */
00246       opt_ignore_aux_cache = 1;
00247       break;
00248     case 'f':
00249       config_file = arg;
00250       break;
00251     case 'i':
00252       opt_ignore_aux_cache = 1;
00253       break;
00254     case 'l':
00255       opt_manual_link = 1;
00256       break;
00257     case 'N':
00258       opt_build_cache = 0;
00259       break;
00260     case 'n':
00261       opt_build_cache = 0;
00262       opt_only_cline = 1;
00263       break;
00264     case 'p':
00265       opt_print_cache = 1;
00266       break;
00267     case 'r':
00268       opt_chroot = arg;
00269       break;
00270     case 'v':
00271       opt_verbose = 1;
00272       break;
00273     case 'X':
00274       opt_link = 0;
00275       break;
00276     case 'c':
00277       if (strcmp (arg, "old") == 0)
00278        opt_format = 0;
00279       else if (strcmp (arg, "compat") == 0)
00280        opt_format = 1;
00281       else if (strcmp (arg, "new") == 0)
00282        opt_format = 2;
00283       break;
00284     default:
00285       return ARGP_ERR_UNKNOWN;
00286     }
00287 
00288   return 0;
00289 }
00290 
00291 /* Print the version information.  */
00292 static void
00293 print_version (FILE *stream, struct argp_state *state)
00294 {
00295   fprintf (stream, "ldconfig (GNU %s) %s\n", PACKAGE, VERSION);
00296   fprintf (stream, gettext ("\
00297 Copyright (C) %s Free Software Foundation, Inc.\n\
00298 This is free software; see the source for copying conditions.  There is NO\n\
00299 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
00300 "), "2008");
00301   fprintf (stream, gettext ("Written by %s.\n"),
00302           "Andreas Jaeger");
00303 }
00304 
00305 /* Add a single directory entry.  */
00306 static void
00307 add_single_dir (struct dir_entry *entry, int verbose)
00308 {
00309   struct dir_entry *ptr, *prev;
00310 
00311   ptr = dir_entries;
00312   prev = ptr;
00313   while (ptr != NULL)
00314     {
00315       /* Check for duplicates.  */
00316       if (ptr->ino == entry->ino && ptr->dev == entry->dev)
00317        {
00318          if (opt_verbose && verbose)
00319            error (0, 0, _("Path `%s' given more than once"), entry->path);
00320          /* Use the newer information.  */
00321          ptr->flag = entry->flag;
00322          free (entry->path);
00323          free (entry);
00324          break;
00325        }
00326       prev = ptr;
00327       ptr = ptr->next;
00328     }
00329   /* Is this the first entry?  */
00330   if (ptr == NULL && dir_entries == NULL)
00331     dir_entries = entry;
00332   else if (ptr == NULL)
00333     prev->next = entry;
00334 }
00335 
00336 /* Add one directory to the list of directories to process.  */
00337 static void
00338 add_dir (const char *line)
00339 {
00340   unsigned int i;
00341   struct dir_entry *entry = xmalloc (sizeof (struct dir_entry));
00342   entry->next = NULL;
00343 
00344   /* Search for an '=' sign.  */
00345   entry->path = xstrdup (line);
00346   char *equal_sign = strchr (entry->path, '=');
00347   if (equal_sign)
00348     {
00349       *equal_sign = '\0';
00350       ++equal_sign;
00351       entry->flag = FLAG_ANY;
00352       for (i = 0; i < sizeof (lib_types) / sizeof (lib_types[0]); ++i)
00353        if (strcmp (equal_sign, lib_types[i].name) == 0)
00354          {
00355            entry->flag = lib_types[i].flag;
00356            break;
00357          }
00358       if (entry->flag == FLAG_ANY)
00359        error (0, 0, _("%s is not a known library type"), equal_sign);
00360     }
00361   else
00362     {
00363       entry->flag = FLAG_ANY;
00364     }
00365 
00366   /* Canonify path: for now only remove leading and trailing
00367      whitespace and the trailing slashes slashes.  */
00368   i = strlen (entry->path) - 1;
00369 
00370   while (isspace (entry->path[i]) && i > 0)
00371     entry->path[i--] = '\0';
00372 
00373   while (entry->path[i] == '/' && i > 0)
00374     entry->path[i--] = '\0';
00375 
00376   char *path = entry->path;
00377   if (opt_chroot)
00378     path = chroot_canon (opt_chroot, path);
00379 
00380   struct stat64 stat_buf;
00381   if (path == NULL || stat64 (path, &stat_buf))
00382     {
00383       if (opt_verbose)
00384        error (0, errno, _("Can't stat %s"), entry->path);
00385       free (entry->path);
00386       free (entry);
00387     }
00388   else
00389     {
00390       entry->ino = stat_buf.st_ino;
00391       entry->dev = stat_buf.st_dev;
00392 
00393       add_single_dir (entry, 1);
00394     }
00395 
00396   if (opt_chroot)
00397     free (path);
00398 }
00399 
00400 
00401 static int
00402 chroot_stat (const char *real_path, const char *path, struct stat64 *st)
00403 {
00404   int ret;
00405   char *canon_path;
00406 
00407   if (!opt_chroot)
00408     return stat64 (real_path, st);
00409 
00410   ret = lstat64 (real_path, st);
00411   if (ret || !S_ISLNK (st->st_mode))
00412     return ret;
00413 
00414   canon_path = chroot_canon (opt_chroot, path);
00415   if (canon_path == NULL)
00416     return -1;
00417 
00418   ret = stat64 (canon_path, st);
00419   free (canon_path);
00420   return ret;
00421 }
00422 
00423 /* Create a symbolic link from soname to libname in directory path.  */
00424 static void
00425 create_links (const char *real_path, const char *path, const char *libname,
00426              const char *soname)
00427 {
00428   char *full_libname, *full_soname;
00429   char *real_full_libname, *real_full_soname;
00430   struct stat64 stat_lib, stat_so, lstat_so;
00431   int do_link = 1;
00432   int do_remove = 1;
00433   /* XXX: The logics in this function should be simplified.  */
00434 
00435   /* Get complete path.  */
00436   full_libname = alloca (strlen (path) + strlen (libname) + 2);
00437   full_soname = alloca (strlen (path) + strlen (soname) + 2);
00438   sprintf (full_libname, "%s/%s", path, libname);
00439   sprintf (full_soname, "%s/%s", path, soname);
00440   if (opt_chroot)
00441     {
00442       real_full_libname = alloca (strlen (real_path) + strlen (libname) + 2);
00443       real_full_soname = alloca (strlen (real_path) + strlen (soname) + 2);
00444       sprintf (real_full_libname, "%s/%s", real_path, libname);
00445       sprintf (real_full_soname, "%s/%s", real_path, soname);
00446     }
00447   else
00448     {
00449       real_full_libname = full_libname;
00450       real_full_soname = full_soname;
00451     }
00452 
00453   /* Does soname already exist and point to the right library?  */
00454   if (chroot_stat (real_full_soname, full_soname, &stat_so) == 0)
00455     {
00456       if (chroot_stat (real_full_libname, full_libname, &stat_lib))
00457        {
00458          error (0, 0, _("Can't stat %s\n"), full_libname);
00459          return;
00460        }
00461       if (stat_lib.st_dev == stat_so.st_dev
00462          && stat_lib.st_ino == stat_so.st_ino)
00463        /* Link is already correct.  */
00464        do_link = 0;
00465       else if (lstat64 (full_soname, &lstat_so) == 0
00466               && !S_ISLNK (lstat_so.st_mode))
00467        {
00468          error (0, 0, _("%s is not a symbolic link\n"), full_soname);
00469          do_link = 0;
00470          do_remove = 0;
00471        }
00472     }
00473   else if (lstat64 (real_full_soname, &lstat_so) != 0
00474           || !S_ISLNK (lstat_so.st_mode))
00475     /* Unless it is a stale symlink, there is no need to remove.  */
00476     do_remove = 0;
00477 
00478   if (opt_verbose)
00479     printf ("\t%s -> %s", soname, libname);
00480 
00481   if (do_link && opt_link)
00482     {
00483       /* Remove old link.  */
00484       if (do_remove)
00485        if (unlink (real_full_soname))
00486          {
00487            error (0, 0, _("Can't unlink %s"), full_soname);
00488            do_link = 0;
00489          }
00490       /* Create symbolic link.  */
00491       if (do_link && symlink (libname, real_full_soname))
00492        {
00493          error (0, 0, _("Can't link %s to %s"), full_soname, libname);
00494          do_link = 0;
00495        }
00496       if (opt_verbose)
00497        {
00498          if (do_link)
00499            fputs (_(" (changed)\n"), stdout);
00500          else
00501            fputs (_(" (SKIPPED)\n"), stdout);
00502        }
00503     }
00504   else if (opt_verbose)
00505     fputs ("\n", stdout);
00506 }
00507 
00508 /* Manually link the given library.  */
00509 static void
00510 manual_link (char *library)
00511 {
00512   char *path;
00513   char *real_path;
00514   char *real_library;
00515   char *libname;
00516   char *soname;
00517   struct stat64 stat_buf;
00518   int flag;
00519   unsigned int osversion;
00520 
00521   /* Prepare arguments for create_links call.  Split library name in
00522      directory and filename first.  Since path is allocated, we've got
00523      to be careful to free at the end.  */
00524   path = xstrdup (library);
00525   libname = strrchr (path, '/');
00526 
00527   if (libname)
00528     {
00529       /* Successfully split names.  Check if path is just "/" to avoid
00530         an empty path.  */
00531       if (libname == path)
00532        {
00533          libname = library + 1;
00534          path = xrealloc (path, 2);
00535          strcpy (path, "/");
00536        }
00537       else
00538        {
00539          *libname = '\0';
00540          ++libname;
00541        }
00542     }
00543   else
00544     {
00545       /* There's no path, construct one. */
00546       libname = library;
00547       path = xrealloc (path, 2);
00548       strcpy (path, ".");
00549     }
00550 
00551   if (opt_chroot)
00552     {
00553       real_path = chroot_canon (opt_chroot, path);
00554       if (real_path == NULL)
00555        {
00556          error (0, errno, _("Can't find %s"), path);
00557          free (path);
00558          return;
00559        }
00560       real_library = alloca (strlen (real_path) + strlen (libname) + 2);
00561       sprintf (real_library, "%s/%s", real_path, libname);
00562     }
00563   else
00564     {
00565       real_path = path;
00566       real_library = library;
00567     }
00568 
00569   /* Do some sanity checks first.  */
00570   if (lstat64 (real_library, &stat_buf))
00571     {
00572       error (0, errno, _("Cannot lstat %s"), library);
00573       free (path);
00574       return;
00575     }
00576   /* We don't want links here!  */
00577   else if (!S_ISREG (stat_buf.st_mode))
00578     {
00579       error (0, 0, _("Ignored file %s since it is not a regular file."),
00580             library);
00581       free (path);
00582       return;
00583     }
00584 
00585   if (process_file (real_library, library, libname, &flag, &osversion,
00586                   &soname, 0, &stat_buf))
00587     {
00588       error (0, 0, _("No link created since soname could not be found for %s"),
00589             library);
00590       free (path);
00591       return;
00592     }
00593   if (soname == NULL)
00594     soname = implicit_soname (libname, flag);
00595   create_links (real_path, path, libname, soname);
00596   free (soname);
00597   free (path);
00598 }
00599 
00600 
00601 /* Read a whole directory and search for libraries.
00602    The purpose is two-fold:
00603    - search for libraries which will be added to the cache
00604    - create symbolic links to the soname for each library
00605 
00606    This has to be done separatly for each directory.
00607 
00608    To keep track of which libraries to add to the cache and which
00609    links to create, we save a list of all libraries.
00610 
00611    The algorithm is basically:
00612    for all libraries in the directory do
00613      get soname of library
00614      if soname is already in list
00615        if new library is newer, replace entry
00616        otherwise ignore this library
00617      otherwise add library to list
00618 
00619    For example, if the two libraries libxy.so.1.1 and libxy.so.1.2
00620    exist and both have the same soname, e.g. libxy.so, a symbolic link
00621    is created from libxy.so.1.2 (the newer one) to libxy.so.
00622    libxy.so.1.2 and libxy.so are added to the cache - but not
00623    libxy.so.1.1.  */
00624 
00625 /* Information for one library.  */
00626 struct dlib_entry
00627 {
00628   char *name;
00629   char *soname;
00630   int flag;
00631   int is_link;
00632   unsigned int osversion;
00633   struct dlib_entry *next;
00634 };
00635 
00636 
00637 static void
00638 search_dir (const struct dir_entry *entry)
00639 {
00640   uint64_t hwcap = path_hwcap (entry->path);
00641   if (opt_verbose)
00642     {
00643       if (hwcap != 0)
00644        printf ("%s: (hwcap: %#.16" PRIx64 ")\n", entry->path, hwcap);
00645       else
00646        printf ("%s:\n", entry->path);
00647     }
00648 
00649   char *dir_name;
00650   char *real_file_name;
00651   size_t real_file_name_len;
00652   size_t file_name_len = PATH_MAX;
00653   char *file_name = alloca (file_name_len);
00654   if (opt_chroot)
00655     {
00656       dir_name = chroot_canon (opt_chroot, entry->path);
00657       real_file_name_len = PATH_MAX;
00658       real_file_name = alloca (real_file_name_len);
00659     }
00660   else
00661     {
00662       dir_name = entry->path;
00663       real_file_name_len = 0;
00664       real_file_name = file_name;
00665     }
00666 
00667   DIR *dir;
00668   if (dir_name == NULL || (dir = opendir (dir_name)) == NULL)
00669     {
00670       if (opt_verbose)
00671        error (0, errno, _("Can't open directory %s"), entry->path);
00672       if (opt_chroot && dir_name)
00673        free (dir_name);
00674       return;
00675     }
00676 
00677   struct dirent64 *direntry;
00678   struct dlib_entry *dlibs = NULL;
00679   while ((direntry = readdir64 (dir)) != NULL)
00680     {
00681       int flag;
00682 #ifdef _DIRENT_HAVE_D_TYPE
00683       /* We only look at links and regular files.  */
00684       if (direntry->d_type != DT_UNKNOWN
00685          && direntry->d_type != DT_LNK
00686          && direntry->d_type != DT_REG
00687          && direntry->d_type != DT_DIR)
00688        continue;
00689 #endif /* _DIRENT_HAVE_D_TYPE  */
00690       /* Does this file look like a shared library or is it a hwcap
00691         subdirectory?  The dynamic linker is also considered as
00692         shared library.  */
00693       if (((strncmp (direntry->d_name, "lib", 3) != 0
00694            && strncmp (direntry->d_name, "ld-", 3) != 0)
00695           || strstr (direntry->d_name, ".so") == NULL)
00696          && (
00697 #ifdef _DIRENT_HAVE_D_TYPE
00698              direntry->d_type == DT_REG ||
00699 #endif
00700              !is_hwcap_platform (direntry->d_name)))
00701        continue;
00702 
00703       size_t len = strlen (direntry->d_name);
00704       /* Skip temporary files created by the prelink program.  Files with
00705         names like these are never really DSOs we want to look at.  */
00706       if (len >= sizeof (".#prelink#") - 1)
00707        {
00708          if (strcmp (direntry->d_name + len - sizeof (".#prelink#") + 1,
00709                     ".#prelink#") == 0)
00710            continue;
00711          if (len >= sizeof (".#prelink#.XXXXXX") - 1
00712              && memcmp (direntry->d_name + len - sizeof (".#prelink#.XXXXXX")
00713                       + 1, ".#prelink#.", sizeof (".#prelink#.") - 1) == 0)
00714            continue;
00715        }
00716       len += strlen (entry->path) + 2;
00717       if (len > file_name_len)
00718        {
00719          file_name_len = len;
00720          file_name = alloca (file_name_len);
00721          if (!opt_chroot)
00722            real_file_name = file_name;
00723        }
00724       sprintf (file_name, "%s/%s", entry->path, direntry->d_name);
00725       if (opt_chroot)
00726        {
00727          len = strlen (dir_name) + strlen (direntry->d_name) + 2;
00728          if (len > real_file_name_len)
00729            {
00730              real_file_name_len = len;
00731              real_file_name = alloca (real_file_name_len);
00732            }
00733          sprintf (real_file_name, "%s/%s", dir_name, direntry->d_name);
00734        }
00735 
00736       struct stat64 lstat_buf;
00737 #ifdef _DIRENT_HAVE_D_TYPE
00738       /* We optimize and try to do the lstat call only if needed.  */
00739       if (direntry->d_type != DT_UNKNOWN)
00740        lstat_buf.st_mode = DTTOIF (direntry->d_type);
00741       else
00742 #endif
00743        if (__builtin_expect (lstat64 (real_file_name, &lstat_buf), 0))
00744          {
00745            error (0, errno, _("Cannot lstat %s"), file_name);
00746            continue;
00747          }
00748 
00749       struct stat64 stat_buf;
00750       int is_dir;
00751       int is_link = S_ISLNK (lstat_buf.st_mode);
00752       if (is_link)
00753        {
00754          /* In case of symlink, we check if the symlink refers to
00755             a directory. */
00756          if (__builtin_expect (stat64 (real_file_name, &stat_buf), 0))
00757            {
00758              if (opt_verbose)
00759               error (0, errno, _("Cannot stat %s"), file_name);
00760 
00761              /* Remove stale symlinks.  */
00762              if (strstr (direntry->d_name, ".so."))
00763               unlink (real_file_name);
00764              continue;
00765            }
00766          is_dir = S_ISDIR (stat_buf.st_mode);
00767 
00768          /* lstat_buf is later stored, update contents.  */
00769          lstat_buf.st_dev = stat_buf.st_dev;
00770          lstat_buf.st_ino = stat_buf.st_ino;
00771          lstat_buf.st_size = stat_buf.st_size;
00772          lstat_buf.st_ctime = stat_buf.st_ctime;
00773        }
00774       else
00775        is_dir = S_ISDIR (lstat_buf.st_mode);
00776 
00777       if (is_dir && is_hwcap_platform (direntry->d_name))
00778        {
00779          /* Handle subdirectory later.  */
00780          struct dir_entry *new_entry;
00781 
00782          new_entry = xmalloc (sizeof (struct dir_entry));
00783          new_entry->path = xstrdup (file_name);
00784          new_entry->flag = entry->flag;
00785          new_entry->next = NULL;
00786 #ifdef _DIRENT_HAVE_D_TYPE
00787          /* We have filled in lstat only #ifndef
00788             _DIRENT_HAVE_D_TYPE.  Fill it in if needed.  */
00789          if (!is_link
00790              && direntry->d_type != DT_UNKNOWN
00791              && __builtin_expect (lstat64 (real_file_name, &lstat_buf), 0))
00792            {
00793              error (0, errno, _("Cannot lstat %s"), file_name);
00794              free (new_entry->path);
00795              free (new_entry);
00796              continue;
00797            }
00798 #endif
00799          new_entry->ino = lstat_buf.st_ino;
00800          new_entry->dev = lstat_buf.st_dev;
00801          add_single_dir (new_entry, 0);
00802          continue;
00803        }
00804       else if (!S_ISREG (lstat_buf.st_mode) && !is_link)
00805        continue;
00806 
00807       char *real_name;
00808       if (opt_chroot && is_link)
00809        {
00810          real_name = chroot_canon (opt_chroot, file_name);
00811          if (real_name == NULL)
00812            {
00813              if (strstr (file_name, ".so") == NULL)
00814               error (0, 0, _("Input file %s not found.\n"), file_name);
00815              continue;
00816            }
00817        }
00818       else
00819        real_name = real_file_name;
00820 
00821 #ifdef _DIRENT_HAVE_D_TYPE
00822       /* Call lstat64 if not done yet.  */
00823       if (!is_link
00824          && direntry->d_type != DT_UNKNOWN
00825          && __builtin_expect (lstat64 (real_file_name, &lstat_buf), 0))
00826        {
00827          error (0, errno, _("Cannot lstat %s"), file_name);
00828          continue;
00829        }
00830 #endif
00831 
00832       /* First search whether the auxiliary cache contains this
00833         library already and it's not changed.  */
00834       char *soname;
00835       unsigned int osversion;
00836       if (!search_aux_cache (&lstat_buf, &flag, &osversion, &soname))
00837        {
00838          if (process_file (real_name, file_name, direntry->d_name, &flag,
00839                          &osversion, &soname, is_link, &lstat_buf))
00840            {
00841              if (real_name != real_file_name)
00842               free (real_name);
00843              continue;
00844            }
00845          else if (opt_build_cache)
00846            add_to_aux_cache (&lstat_buf, flag, osversion, soname);
00847        }
00848 
00849       if (soname == NULL)
00850        soname = implicit_soname (direntry->d_name, flag);
00851 
00852       /* A link may just point to itself.  */
00853       if (is_link)
00854        {
00855          /* If the path the link points to isn't its soname and it is not
00856             .so symlink for ld(1) only, we treat it as a normal file.  */
00857          const char *real_base_name = basename (real_file_name);
00858 
00859          if (strcmp (real_base_name, soname) != 0)
00860            {
00861              len = strlen (real_base_name);
00862              if (len < strlen (".so")
00863                 || strcmp (real_base_name + len - strlen (".so"), ".so") != 0
00864                 || strncmp (real_base_name, soname, len) != 0)
00865               is_link = 0;
00866            }
00867        }
00868 
00869       if (real_name != real_file_name)
00870        free (real_name);
00871 
00872       if (is_link)
00873        {
00874          free (soname);
00875          soname = xstrdup (direntry->d_name);
00876        }
00877 
00878       if (flag == FLAG_ELF
00879          && (entry->flag == FLAG_ELF_LIBC5
00880              || entry->flag == FLAG_ELF_LIBC6))
00881        flag = entry->flag;
00882 
00883       /* Some sanity checks to print warnings.  */
00884       if (opt_verbose)
00885        {
00886          if (flag == FLAG_ELF_LIBC5 && entry->flag != FLAG_ELF_LIBC5
00887              && entry->flag != FLAG_ANY)
00888            error (0, 0, _("libc5 library %s in wrong directory"), file_name);
00889          if (flag == FLAG_ELF_LIBC6 && entry->flag != FLAG_ELF_LIBC6
00890              && entry->flag != FLAG_ANY)
00891            error (0, 0, _("libc6 library %s in wrong directory"), file_name);
00892          if (flag == FLAG_LIBC4 && entry->flag != FLAG_LIBC4
00893              && entry->flag != FLAG_ANY)
00894            error (0, 0, _("libc4 library %s in wrong directory"), file_name);
00895        }
00896 
00897       /* Add library to list.  */
00898       struct dlib_entry *dlib_ptr;
00899       for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next)
00900        {
00901          /* Is soname already in list?  */
00902          if (strcmp (dlib_ptr->soname, soname) == 0)
00903            {
00904              /* Prefer a file to a link, otherwise check which one
00905                is newer.  */
00906              if ((!is_link && dlib_ptr->is_link)
00907                 || (is_link == dlib_ptr->is_link
00908                     && _dl_cache_libcmp (dlib_ptr->name, direntry->d_name) < 0))
00909               {
00910                 /* It's newer - add it.  */
00911                 /* Flag should be the same - sanity check.  */
00912                 if (dlib_ptr->flag != flag)
00913                   {
00914                     if (dlib_ptr->flag == FLAG_ELF
00915                        && (flag == FLAG_ELF_LIBC5 || flag == FLAG_ELF_LIBC6))
00916                      dlib_ptr->flag = flag;
00917                     else if ((dlib_ptr->flag == FLAG_ELF_LIBC5
00918                             || dlib_ptr->flag == FLAG_ELF_LIBC6)
00919                             && flag == FLAG_ELF)
00920                      dlib_ptr->flag = flag;
00921                     else
00922                      error (0, 0, _("libraries %s and %s in directory %s have same soname but different type."),
00923                             dlib_ptr->name, direntry->d_name,
00924                             entry->path);
00925                   }
00926                 free (dlib_ptr->name);
00927                 dlib_ptr->name = xstrdup (direntry->d_name);
00928                 dlib_ptr->is_link = is_link;
00929                 dlib_ptr->osversion = osversion;
00930               }
00931              /* Don't add this library, abort loop.  */
00932              /* Also free soname, since it's dynamically allocated.  */
00933              free (soname);
00934              break;
00935            }
00936        }
00937       /* Add the library if it's not already in.  */
00938       if (dlib_ptr == NULL)
00939        {
00940          dlib_ptr = (struct dlib_entry *)xmalloc (sizeof (struct dlib_entry));
00941          dlib_ptr->name = xstrdup (direntry->d_name);
00942          dlib_ptr->soname = soname;
00943          dlib_ptr->flag = flag;
00944          dlib_ptr->is_link = is_link;
00945          dlib_ptr->osversion = osversion;
00946          /* Add at head of list.  */
00947          dlib_ptr->next = dlibs;
00948          dlibs = dlib_ptr;
00949        }
00950     }
00951 
00952   closedir (dir);
00953 
00954   /* Now dlibs contains a list of all libs - add those to the cache
00955      and created all symbolic links.  */
00956   struct dlib_entry *dlib_ptr;
00957   for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next)
00958     {
00959       /* Don't create links to links.  */
00960       if (dlib_ptr->is_link == 0)
00961        create_links (dir_name, entry->path, dlib_ptr->name,
00962                     dlib_ptr->soname);
00963       if (opt_build_cache)
00964        add_to_cache (entry->path, dlib_ptr->soname, dlib_ptr->flag,
00965                     dlib_ptr->osversion, hwcap);
00966     }
00967 
00968   /* Free all resources.  */
00969   while (dlibs)
00970     {
00971       dlib_ptr = dlibs;
00972       free (dlib_ptr->soname);
00973       free (dlib_ptr->name);
00974       dlibs = dlibs->next;
00975       free (dlib_ptr);
00976     }
00977 
00978   if (opt_chroot && dir_name)
00979     free (dir_name);
00980 }
00981 
00982 /* Search through all libraries.  */
00983 static void
00984 search_dirs (void)
00985 {
00986   struct dir_entry *entry;
00987 
00988   for (entry = dir_entries; entry != NULL; entry = entry->next)
00989     search_dir (entry);
00990 
00991   /* Free all allocated memory.  */
00992   while (dir_entries)
00993     {
00994       entry = dir_entries;
00995       dir_entries = dir_entries->next;
00996       free (entry->path);
00997       free (entry);
00998     }
00999 }
01000 
01001 
01002 static void parse_conf_include (const char *config_file, unsigned int lineno,
01003                             bool do_chroot, const char *pattern);
01004 
01005 /* Parse configuration file.  */
01006 static void
01007 parse_conf (const char *filename, bool do_chroot)
01008 {
01009   FILE *file = NULL;
01010   char *line = NULL;
01011   const char *canon;
01012   size_t len = 0;
01013   unsigned int lineno;
01014 
01015   if (do_chroot && opt_chroot)
01016     {
01017       canon = chroot_canon (opt_chroot, filename);
01018       if (canon)
01019        file = fopen (canon, "r");
01020       else
01021        canon = filename;
01022     }
01023   else
01024     {
01025       canon = filename;
01026       file = fopen (filename, "r");
01027     }
01028 
01029   if (file == NULL)
01030     {
01031       error (0, errno, _("Can't open configuration file %s"), canon);
01032       if (canon != filename)
01033        free ((char *) canon);
01034       return;
01035     }
01036 
01037   /* No threads use this stream.  */
01038   __fsetlocking (file, FSETLOCKING_BYCALLER);
01039 
01040   if (canon != filename)
01041     free ((char *) canon);
01042 
01043   lineno = 0;
01044   do
01045     {
01046       ssize_t n = getline (&line, &len, file);
01047       if (n < 0)
01048        break;
01049 
01050       ++lineno;
01051       if (line[n - 1] == '\n')
01052        line[n - 1] = '\0';
01053 
01054       /* Because the file format does not know any form of quoting we
01055         can search forward for the next '#' character and if found
01056         make it terminating the line.  */
01057       *strchrnul (line, '#') = '\0';
01058 
01059       /* Remove leading whitespace.  NUL is no whitespace character.  */
01060       char *cp = line;
01061       while (isspace (*cp))
01062        ++cp;
01063 
01064       /* If the line is blank it is ignored.  */
01065       if (cp[0] == '\0')
01066        continue;
01067 
01068       if (!strncmp (cp, "include", 7) && isblank (cp[7]))
01069        {
01070          char *dir;
01071          cp += 8;
01072          while ((dir = strsep (&cp, " \t")) != NULL)
01073            if (dir[0] != '\0')
01074              parse_conf_include (filename, lineno, do_chroot, dir);
01075        }
01076       else if (!strncasecmp (cp, "hwcap", 5) && isblank (cp[5]))
01077        {
01078          cp += 6;
01079          char *p, *name = NULL;
01080          unsigned long int n = strtoul (cp, &cp, 0);
01081          if (cp != NULL && isblank (*cp))
01082            while ((p = strsep (&cp, " \t")) != NULL)
01083              if (p[0] != '\0')
01084               {
01085                 if (name == NULL)
01086                   name = p;
01087                 else
01088                   {
01089                     name = NULL;
01090                     break;
01091                   }
01092               }
01093          if (name == NULL)
01094            {
01095              error (EXIT_FAILURE, 0, _("%s:%u: bad syntax in hwcap line"),
01096                    filename, lineno);
01097              break;
01098            }
01099          if (n >= (64 - _DL_FIRST_EXTRA))
01100            error (EXIT_FAILURE, 0,
01101                  _("%s:%u: hwcap index %lu above maximum %u"),
01102                  filename, lineno, n, 64 - _DL_FIRST_EXTRA - 1);
01103          if (hwcap_extra[n] == NULL)
01104            {
01105              for (unsigned long int h = 0; h < (64 - _DL_FIRST_EXTRA); ++h)
01106               if (hwcap_extra[h] != NULL && !strcmp (name, hwcap_extra[h]))
01107                 error (EXIT_FAILURE, 0,
01108                       _("%s:%u: hwcap index %lu already defined as %s"),
01109                       filename, lineno, h, name);
01110              hwcap_extra[n] = xstrdup (name);
01111            }
01112          else
01113            {
01114              if (strcmp (name, hwcap_extra[n]))
01115               error (EXIT_FAILURE, 0,
01116                      _("%s:%u: hwcap index %lu already defined as %s"),
01117                      filename, lineno, n, hwcap_extra[n]);
01118              if (opt_verbose)
01119               error (0, 0, _("%s:%u: duplicate hwcap %lu %s"),
01120                      filename, lineno, n, name);
01121            }
01122        }
01123       else
01124        add_dir (cp);
01125     }
01126   while (!feof_unlocked (file));
01127 
01128   /* Free buffer and close file.  */
01129   free (line);
01130   fclose (file);
01131 }
01132 
01133 /* Handle one word in an `include' line, a glob pattern of additional
01134    config files to read.  */
01135 static void
01136 parse_conf_include (const char *config_file, unsigned int lineno,
01137                   bool do_chroot, const char *pattern)
01138 {
01139   if (opt_chroot && pattern[0] != '/')
01140     error (EXIT_FAILURE, 0,
01141           _("need absolute file name for configuration file when using -r"));
01142 
01143   char *copy = NULL;
01144   if (pattern[0] != '/' && strchr (config_file, '/') != NULL)
01145     {
01146       if (asprintf (&copy, "%s/%s", dirname (strdupa (config_file)),
01147                   pattern) < 0)
01148        error (EXIT_FAILURE, 0, _("memory exhausted"));
01149       pattern = copy;
01150     }
01151 
01152   glob64_t gl;
01153   int result;
01154   if (do_chroot && opt_chroot)
01155     {
01156       char *canon = chroot_canon (opt_chroot, pattern);
01157       result = glob64 (canon ?: pattern, 0, NULL, &gl);
01158       free (canon);
01159     }
01160   else
01161     result = glob64 (pattern, 0, NULL, &gl);
01162 
01163   switch (result)
01164     {
01165     case 0:
01166       for (size_t i = 0; i < gl.gl_pathc; ++i)
01167        parse_conf (gl.gl_pathv[i], false);
01168       globfree64 (&gl);
01169       break;
01170 
01171     case GLOB_NOMATCH:
01172       break;
01173 
01174     case GLOB_NOSPACE:
01175       errno = ENOMEM;
01176     case GLOB_ABORTED:
01177       if (opt_verbose)
01178        error (0, errno, _("%s:%u: cannot read directory %s"),
01179               config_file, lineno, pattern);
01180       break;
01181 
01182     default:
01183       abort ();
01184       break;
01185     }
01186 
01187   free (copy);
01188 }
01189 
01190 /* Honour LD_HWCAP_MASK.  */
01191 static void
01192 set_hwcap (void)
01193 {
01194   char *mask = getenv ("LD_HWCAP_MASK");
01195 
01196   if (mask)
01197     hwcap_mask = strtoul (mask, NULL, 0);
01198 }
01199 
01200 
01201 int
01202 main (int argc, char **argv)
01203 {
01204   /* Set locale via LC_ALL.  */
01205   setlocale (LC_ALL, "");
01206 
01207   /* Set the text message domain.  */
01208   textdomain (_libc_intl_domainname);
01209 
01210   /* Parse and process arguments.  */
01211   int remaining;
01212   argp_parse (&argp, argc, argv, 0, &remaining, NULL);
01213 
01214   /* Remaining arguments are additional directories if opt_manual_link
01215      is not set.  */
01216   if (remaining != argc && !opt_manual_link)
01217     {
01218       int i;
01219       for (i = remaining; i < argc; ++i)
01220        if (opt_build_cache && argv[i][0] != '/')
01221          error (EXIT_FAILURE, 0,
01222                _("relative path `%s' used to build cache"),
01223                argv[i]);
01224        else
01225          add_dir (argv[i]);
01226     }
01227 
01228   hwcap_extra[63 - _DL_FIRST_EXTRA] = "tls";
01229 
01230   set_hwcap ();
01231 
01232   if (opt_chroot)
01233     {
01234       /* Normalize the path a bit, we might need it for printing later.  */
01235       char *endp = rawmemchr (opt_chroot, '\0');
01236       while (endp > opt_chroot && endp[-1] == '/')
01237        --endp;
01238       *endp = '\0';
01239       if (endp == opt_chroot)
01240        opt_chroot = NULL;
01241 
01242       if (opt_chroot)
01243        {
01244          /* It is faster to use chroot if we can.  */
01245          if (!chroot (opt_chroot))
01246            {
01247              if (chdir ("/"))
01248               error (EXIT_FAILURE, errno, _("Can't chdir to /"));
01249              opt_chroot = NULL;
01250            }
01251        }
01252     }
01253 
01254   if (cache_file == NULL)
01255     {
01256       cache_file = alloca (strlen (LD_SO_CACHE) + 1);
01257       strcpy (cache_file, LD_SO_CACHE);
01258     }
01259 
01260   if (config_file == NULL)
01261     config_file = LD_SO_CONF;
01262 
01263   if (opt_print_cache)
01264     {
01265       if (opt_chroot)
01266        {
01267          char *p = chroot_canon (opt_chroot, cache_file);
01268          if (p == NULL)
01269            error (EXIT_FAILURE, errno, _("Can't open cache file %s\n"),
01270                  cache_file);
01271          cache_file = p;
01272        }
01273       print_cache (cache_file);
01274       if (opt_chroot)
01275        free (cache_file);
01276       exit (0);
01277     }
01278 
01279   if (opt_chroot)
01280     {
01281       /* Canonicalize the directory name of cache_file, not cache_file,
01282         because we'll rename a temporary cache file to it.  */
01283       char *p = strrchr (cache_file, '/');
01284       char *canon = chroot_canon (opt_chroot,
01285                               p ? (*p = '\0', cache_file) : "/");
01286 
01287       if (canon == NULL)
01288        {
01289          error (EXIT_FAILURE, errno,
01290                _("Can't open cache file directory %s\n"),
01291                p ? cache_file : "/");
01292        }
01293 
01294       if (p)
01295        ++p;
01296       else
01297        p = cache_file;
01298 
01299       cache_file = alloca (strlen (canon) + strlen (p) + 2);
01300       sprintf (cache_file, "%s/%s", canon, p);
01301       free (canon);
01302     }
01303 
01304   if (opt_manual_link)
01305     {
01306       /* Link all given libraries manually.  */
01307       int i;
01308 
01309       for (i = remaining; i < argc; ++i)
01310        manual_link (argv[i]);
01311 
01312       exit (0);
01313     }
01314 
01315 
01316   if (opt_build_cache)
01317     init_cache ();
01318 
01319   if (!opt_only_cline)
01320     {
01321       parse_conf (config_file, true);
01322 
01323       /* Always add the standard search paths.  */
01324       add_system_dir (SLIBDIR);
01325       if (strcmp (SLIBDIR, LIBDIR))
01326        add_system_dir (LIBDIR);
01327     }
01328 
01329   if (! opt_ignore_aux_cache)
01330     load_aux_cache (_PATH_LDCONFIG_AUX_CACHE);
01331   else
01332     init_aux_cache ();
01333 
01334   search_dirs ();
01335 
01336   if (opt_build_cache)
01337     {
01338       save_cache (cache_file);
01339       save_aux_cache (_PATH_LDCONFIG_AUX_CACHE);
01340     }
01341 
01342   return 0;
01343 }