(linenum→info "unix/slp.c:2238")

glibc/2.7/elf/ldconfig.c

    1: /* Copyright (C) 1999-2004, 2005, 2006, 2007 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:    This program is free software; you can redistribute it and/or modify
    6:    it under the terms of the GNU General Public License as published
    7:    by the Free Software Foundation; version 2 of the License, or
    8:    (at your option) any later version.
    9: 
   10:    This program 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
   13:    GNU General Public License for more details.
   14: 
   15:    You should have received a copy of the GNU General Public License
   16:    along with this program; if not, write to the Free Software Foundation,
   17:    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
   18: 
   19: #define PROCINFO_CLASS static
   20: #include <alloca.h>
   21: #include <argp.h>
   22: #include <dirent.h>
   23: #include <elf.h>
   24: #include <error.h>
   25: #include <errno.h>
   26: #include <inttypes.h>
   27: #include <libintl.h>
   28: #include <locale.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: /* Should we ignore an old auxiliary cache file?  */
  116: static int opt_ignore_aux_cache;
  117: 
  118: /* Cache file to use.  */
  119: static char *cache_file;
  120: 
  121: /* Configuration file.  */
  122: static const char *config_file;
  123: 
  124: /* Mask to use for important hardware capabilities.  */
  125: static unsigned long int hwcap_mask = HWCAP_IMPORTANT;
  126: 
  127: /* Configuration-defined capabilities defined in kernel vDSOs.  */
  128: static const char *hwcap_extra[64 - _DL_FIRST_EXTRA];
  129: 
  130: /* Name and version of program.  */
  131: static void print_version (FILE *stream, struct argp_state *state);
  132: void (*argp_program_version_hook) (FILE *, struct argp_state *)
  133:      = print_version;
  134: 
  135: /* Definitions of arguments for argp functions.  */
  136: static const struct argp_option options[] =
  137: {
  138:   { "print-cache", 'p', NULL, 0, N_("Print cache"), 0},
  139:   { "verbose", 'v', NULL, 0, N_("Generate verbose messages"), 0},
  140:   { NULL, 'N', NULL, 0, N_("Don't build cache"), 0},
  141:   { NULL, 'X', NULL, 0, N_("Don't generate links"), 0},
  142:   { NULL, 'r', N_("ROOT"), 0, N_("Change to and use ROOT as root directory"), 0},
  143:   { NULL, 'C', N_("CACHE"), 0, N_("Use CACHE as cache file"), 0},
  144:   { NULL, 'f', N_("CONF"), 0, N_("Use CONF as configuration file"), 0},
  145:   { NULL, 'n', NULL, 0, N_("Only process directories specified on the command line.  Don't build cache."), 0},
  146:   { NULL, 'l', NULL, 0, N_("Manually link individual libraries."), 0},
  147:   { "format", 'c', N_("FORMAT"), 0, N_("Format to use: new, old or compat (default)"), 0},
  148:   { "ignore-aux-cache", 'i', NULL, 0, N_("Ignore auxiliary cache file"), 0},
  149:   { NULL, 0, NULL, 0, NULL, 0 }
  150: };
  151: 
  152: #define PROCINFO_CLASS static
  153: #include <dl-procinfo.c>
  154: 
  155: /* Short description of program.  */
  156: static const char doc[] = N_("Configure Dynamic Linker Run Time Bindings.");
  157: 
  158: /* Prototype for option handler.  */
  159: static error_t parse_opt (int key, char *arg, struct argp_state *state);
  160: 
  161: /* Data structure to communicate with argp functions.  */
  162: static struct argp argp =
  163: {
  164:   options, parse_opt, NULL, doc, NULL, NULL, NULL
  165: };
  166: 
  167: /* Check if string corresponds to an important hardware capability or
  168:    a platform.  */
  169: static int
  170: is_hwcap_platform (const char *name)
  171: {
  172:   int hwcap_idx = _dl_string_hwcap (name);
  173: 
  174:   if (hwcap_idx != -1 && ((1 << hwcap_idx) & hwcap_mask))
  175:     return 1;
  176: 
  177:   hwcap_idx = _dl_string_platform (name);
  178:   if (hwcap_idx != -1)
  179:     return 1;
  180: 
  181:   for (hwcap_idx = _DL_FIRST_EXTRA; hwcap_idx < 64; ++hwcap_idx)
  182:     if (hwcap_extra[hwcap_idx - _DL_FIRST_EXTRA] != NULL
  183:         && !strcmp (name, hwcap_extra[hwcap_idx - _DL_FIRST_EXTRA]))
  184:       return 1;
  185: 
  186:   return 0;
  187: }
  188: 
  189: /* Get hwcap (including platform) encoding of path.  */
  190: static uint64_t
  191: path_hwcap (const char *path)
  192: {
  193:   char *str = xstrdup (path);
  194:   char *ptr;
  195:   uint64_t hwcap = 0;
  196:   uint64_t h;
  197: 
  198:   size_t len;
  199: 
  200:   len = strlen (str);
  201:   if (str[len] == '/')
  202:     str[len] = '\0';
  203: 
  204:   /* Search pathname from the end and check for hwcap strings.  */
  205:   for (;;)
  206:     {
  207:       ptr = strrchr (str, '/');
  208: 
  209:       if (ptr == NULL)
  210:         break;
  211: 
  212:       h = _dl_string_hwcap (ptr + 1);
  213: 
  214:       if (h == (uint64_t) -1)
  215:         {
  216:           h = _dl_string_platform (ptr + 1);
  217:           if (h == (uint64_t) -1)
  218:             {
  219:               for (h = _DL_FIRST_EXTRA; h < 64; ++h)
  220:                 if (hwcap_extra[h - _DL_FIRST_EXTRA] != NULL
  221:                     && !strcmp (ptr + 1, hwcap_extra[h - _DL_FIRST_EXTRA]))
  222:                   break;
  223:               if (h == 64)
  224:                 break;
  225:             }
  226:         }
  227:       hwcap += 1ULL << h;
  228: 
  229:       /* Search the next part of the path.  */
  230:       *ptr = '\0';
  231:     }
  232: 
  233:   free (str);
  234:   return hwcap;
  235: }
  236: 
  237: /* Handle program arguments.  */
  238: static error_t
  239: parse_opt (int key, char *arg, struct argp_state *state)
  240: {
  241:   switch (key)
  242:     {
  243:     case 'C':
  244:       cache_file = arg;
  245:       /* Ignore auxiliary cache since we use non-standard cache.  */
  246:       opt_ignore_aux_cache = 1;
  247:       break;
  248:     case 'f':
  249:       config_file = arg;
  250:       break;
  251:     case 'i':
  252:       opt_ignore_aux_cache = 1;
  253:       break;
  254:     case 'l':
  255:       opt_manual_link = 1;
  256:       break;
  257:     case 'N':
  258:       opt_build_cache = 0;
  259:       break;
  260:     case 'n':
  261:       opt_build_cache = 0;
  262:       opt_only_cline = 1;
  263:       break;
  264:     case 'p':
  265:       opt_print_cache = 1;
  266:       break;
  267:     case 'r':
  268:       opt_chroot = arg;
  269:       break;
  270:     case 'v':
  271:       opt_verbose = 1;
  272:       break;
  273:     case 'X':
  274:       opt_link = 0;
  275:       break;
  276:     case 'c':
  277:       if (strcmp (arg, "old") == 0)
  278:         opt_format = 0;
  279:       else if (strcmp (arg, "compat") == 0)
  280:         opt_format = 1;
  281:       else if (strcmp (arg, "new") == 0)
  282:         opt_format = 2;
  283:       break;
  284:     default:
  285:       return ARGP_ERR_UNKNOWN;
  286:     }
  287: 
  288:   return 0;
  289: }
  290: 
  291: /* Print the version information.  */
  292: static void
  293: print_version (FILE *stream, struct argp_state *state)
  294: {
  295:   fprintf (stream, "ldconfig (GNU %s) %s\n", PACKAGE, VERSION);
  296:   fprintf (stream, gettext ("\
  297: Copyright (C) %s Free Software Foundation, Inc.\n\
  298: This is free software; see the source for copying conditions.  There is NO\n\
  299: warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
  300: "), "2007");
  301:   fprintf (stream, gettext ("Written by %s.\n"),
  302:            "Andreas Jaeger");
  303: }
  304: 
  305: /* Add a single directory entry.  */
  306: static void
  307: add_single_dir (struct dir_entry *entry, int verbose)
  308: {
  309:   struct dir_entry *ptr, *prev;
  310: 
  311:   ptr = dir_entries;
  312:   prev = ptr;
  313:   while (ptr != NULL)
  314:     {
  315:       /* Check for duplicates.  */
  316:       if (ptr->ino == entry->ino && ptr->dev == entry->dev)
  317:         {
  318:           if (opt_verbose && verbose)
  319:             error (0, 0, _("Path `%s' given more than once"), entry->path);
  320:           /* Use the newer information.  */
  321:           ptr->flag = entry->flag;
  322:           free (entry->path);
  323:           free (entry);
  324:           break;
  325:         }
  326:       prev = ptr;
  327:       ptr = ptr->next;
  328:     }
  329:   /* Is this the first entry?  */
  330:   if (ptr == NULL && dir_entries == NULL)
  331:     dir_entries = entry;
  332:   else if (ptr == NULL)
  333:     prev->next = entry;
  334: }
  335: 
  336: /* Add one directory to the list of directories to process.  */
  337: static void
  338: add_dir (const char *line)
  339: {
  340:   unsigned int i;
  341:   struct dir_entry *entry = xmalloc (sizeof (struct dir_entry));
  342:   entry->next = NULL;
  343: 
  344:   /* Search for an '=' sign.  */
  345:   entry->path = xstrdup (line);
  346:   char *equal_sign = strchr (entry->path, '=');
  347:   if (equal_sign)
  348:     {
  349:       *equal_sign = '\0';
  350:       ++equal_sign;
  351:       entry->flag = FLAG_ANY;
  352:       for (i = 0; i < sizeof (lib_types) / sizeof (lib_types[0]); ++i)
  353:         if (strcmp (equal_sign, lib_types[i].name) == 0)
  354:           {
  355:             entry->flag = lib_types[i].flag;
  356:             break;
  357:           }
  358:       if (entry->flag == FLAG_ANY)
  359:         error (0, 0, _("%s is not a known library type"), equal_sign);
  360:     }
  361:   else
  362:     {
  363:       entry->flag = FLAG_ANY;
  364:     }
  365: 
  366:   /* Canonify path: for now only remove leading and trailing
  367:      whitespace and the trailing slashes slashes.  */
  368:   i = strlen (entry->path) - 1;
  369: 
  370:   while (isspace (entry->path[i]) && i > 0)
  371:     entry->path[i--] = '\0';
  372: 
  373:   while (entry->path[i] == '/' && i > 0)
  374:     entry->path[i--] = '\0';
  375: 
  376:   char *path = entry->path;
  377:   if (opt_chroot)
  378:     path = chroot_canon (opt_chroot, path);
  379: 
  380:   struct stat64 stat_buf;
  381:   if (path == NULL || stat64 (path, &stat_buf))
  382:     {
  383:       if (opt_verbose)
  384:         error (0, errno, _("Can't stat %s"), entry->path);
  385:       free (entry->path);
  386:       free (entry);
  387:     }
  388:   else
  389:     {
  390:       entry->ino = stat_buf.st_ino;
  391:       entry->dev = stat_buf.st_dev;
  392: 
  393:       add_single_dir (entry, 1);
  394:     }
  395: 
  396:   if (opt_chroot)
  397:     free (path);
  398: }
  399: 
  400: 
  401: static int
  402: chroot_stat (const char *real_path, const char *path, struct stat64 *st)
  403: {
  404:   int ret;
  405:   char *canon_path;
  406: 
  407:   if (!opt_chroot)
  408:     return stat64 (real_path, st);
  409: 
  410:   ret = lstat64 (real_path, st);
  411:   if (ret || !S_ISLNK (st->st_mode))
  412:     return ret;
  413: 
  414:   canon_path = chroot_canon (opt_chroot, path);
  415:   if (canon_path == NULL)
  416:     return -1;
  417: 
  418:   ret = stat64 (canon_path, st);
  419:   free (canon_path);
  420:   return ret;
  421: }
  422: 
  423: /* Create a symbolic link from soname to libname in directory path.  */
  424: static void
  425: create_links (const char *real_path, const char *path, const char *libname,
  426:               const char *soname)
  427: {
  428:   char *full_libname, *full_soname;
  429:   char *real_full_libname, *real_full_soname;
  430:   struct stat64 stat_lib, stat_so, lstat_so;
  431:   int do_link = 1;
  432:   int do_remove = 1;
  433:   /* XXX: The logics in this function should be simplified.  */
  434: 
  435:   /* Get complete path.  */
  436:   full_libname = alloca (strlen (path) + strlen (libname) + 2);
  437:   full_soname = alloca (strlen (path) + strlen (soname) + 2);
  438:   sprintf (full_libname, "%s/%s", path, libname);
  439:   sprintf (full_soname, "%s/%s", path, soname);
  440:   if (opt_chroot)
  441:     {
  442:       real_full_libname = alloca (strlen (real_path) + strlen (libname) + 2);
  443:       real_full_soname = alloca (strlen (real_path) + strlen (soname) + 2);
  444:       sprintf (real_full_libname, "%s/%s", real_path, libname);
  445:       sprintf (real_full_soname, "%s/%s", real_path, soname);
  446:     }
  447:   else
  448:     {
  449:       real_full_libname = full_libname;
  450:       real_full_soname = full_soname;
  451:     }
  452: 
  453:   /* Does soname already exist and point to the right library?  */
  454:   if (chroot_stat (real_full_soname, full_soname, &stat_so) == 0)
  455:     {
  456:       if (chroot_stat (real_full_libname, full_libname, &stat_lib))
  457:         {
  458:           error (0, 0, _("Can't stat %s\n"), full_libname);
  459:           return;
  460:         }
  461:       if (stat_lib.st_dev == stat_so.st_dev
  462:           && stat_lib.st_ino == stat_so.st_ino)
  463:         /* Link is already correct.  */
  464:         do_link = 0;
  465:       else if (lstat64 (full_soname, &lstat_so) == 0
  466:                && !S_ISLNK (lstat_so.st_mode))
  467:         {
  468:           error (0, 0, _("%s is not a symbolic link\n"), full_soname);
  469:           do_link = 0;
  470:           do_remove = 0;
  471:         }
  472:     }
  473:   else if (lstat64 (real_full_soname, &lstat_so) != 0
  474:            || !S_ISLNK (lstat_so.st_mode))
  475:     /* Unless it is a stale symlink, there is no need to remove.  */
  476:     do_remove = 0;
  477: 
  478:   if (opt_verbose)
  479:     printf ("\t%s -> %s", soname, libname);
  480: 
  481:   if (do_link && opt_link)
  482:     {
  483:       /* Remove old link.  */
  484:       if (do_remove)
  485:         if (unlink (real_full_soname))
  486:           {
  487:             error (0, 0, _("Can't unlink %s"), full_soname);
  488:             do_link = 0;
  489:           }
  490:       /* Create symbolic link.  */
  491:       if (do_link && symlink (libname, real_full_soname))
  492:         {
  493:           error (0, 0, _("Can't link %s to %s"), full_soname, libname);
  494:           do_link = 0;
  495:         }
  496:       if (opt_verbose)
  497:         {
  498:           if (do_link)
  499:             fputs (_(" (changed)\n"), stdout);
  500:           else
  501:             fputs (_(" (SKIPPED)\n"), stdout);
  502:         }
  503:     }
  504:   else if (opt_verbose)
  505:     fputs ("\n", stdout);
  506: }
  507: 
  508: /* Manually link the given library.  */
  509: static void
  510: manual_link (char *library)
  511: {
  512:   char *path;
  513:   char *real_path;
  514:   char *real_library;
  515:   char *libname;
  516:   char *soname;
  517:   struct stat64 stat_buf;
  518:   int flag;
  519:   unsigned int osversion;
  520: 
  521:   /* Prepare arguments for create_links call.  Split library name in
  522:      directory and filename first.  Since path is allocated, we've got
  523:      to be careful to free at the end.  */
  524:   path = xstrdup (library);
  525:   libname = strrchr (path, '/');
  526: 
  527:   if (libname)
  528:     {
  529:       /* Successfully split names.  Check if path is just "/" to avoid
  530:          an empty path.  */
  531:       if (libname == path)
  532:         {
  533:           libname = library + 1;
  534:           path = xrealloc (path, 2);
  535:           strcpy (path, "/");
  536:         }
  537:       else
  538:         {
  539:           *libname = '\0';
  540:           ++libname;
  541:         }
  542:     }
  543:   else
  544:     {
  545:       /* There's no path, construct one. */
  546:       libname = library;
  547:       path = xrealloc (path, 2);
  548:       strcpy (path, ".");
  549:     }
  550: 
  551:   if (opt_chroot)
  552:     {
  553:       real_path = chroot_canon (opt_chroot, path);
  554:       if (real_path == NULL)
  555:         {
  556:           error (0, errno, _("Can't find %s"), path);
  557:           free (path);
  558:           return;
  559:         }
  560:       real_library = alloca (strlen (real_path) + strlen (libname) + 2);
  561:       sprintf (real_library, "%s/%s", real_path, libname);
  562:     }
  563:   else
  564:     {
  565:       real_path = path;
  566:       real_library = library;
  567:     }
  568: 
  569:   /* Do some sanity checks first.  */
  570:   if (lstat64 (real_library, &stat_buf))
  571:     {
  572:       error (0, errno, _("Cannot lstat %s"), library);
  573:       free (path);
  574:       return;
  575:     }
  576:   /* We don't want links here!  */
  577:   else if (!S_ISREG (stat_buf.st_mode))
  578:     {
  579:       error (0, 0, _("Ignored file %s since it is not a regular file."),
  580:              library);
  581:       free (path);
  582:       return;
  583:     }
  584: 
  585:   if (process_file (real_library, library, libname, &flag, &osversion,
  586:                     &soname, 0, &stat_buf))
  587:     {
  588:       error (0, 0, _("No link created since soname could not be found for %s"),
  589: