1696Spaul/* 214260Spst * Copyright (c) 1993,1995 Paul Kranenburg 3696Spaul * All rights reserved. 4696Spaul * 5696Spaul * Redistribution and use in source and binary forms, with or without 6696Spaul * modification, are permitted provided that the following conditions 7696Spaul * are met: 8696Spaul * 1. Redistributions of source code must retain the above copyright 9696Spaul * notice, this list of conditions and the following disclaimer. 10696Spaul * 2. Redistributions in binary form must reproduce the above copyright 11696Spaul * notice, this list of conditions and the following disclaimer in the 12696Spaul * documentation and/or other materials provided with the distribution. 13696Spaul * 3. All advertising materials mentioning features or use of this software 14696Spaul * must display the following acknowledgement: 15696Spaul * This product includes software developed by Paul Kranenburg. 16696Spaul * 4. The name of the author may not be used to endorse or promote products 171153Sjkh * derived from this software without specific prior written permission 18696Spaul * 19696Spaul * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20696Spaul * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21696Spaul * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22696Spaul * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23696Spaul * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24696Spaul * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25696Spaul * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26696Spaul * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27696Spaul * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28696Spaul * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29696Spaul */ 30696Spaul 3137420Scharnier#ifndef lint 3237420Scharnierstatic const char rcsid[] = 3350476Speter "$FreeBSD$"; 3437420Scharnier#endif /* not lint */ 3537420Scharnier 36696Spaul#include <sys/param.h> 37696Spaul#include <sys/types.h> 38696Spaul#include <sys/stat.h> 39696Spaul#include <sys/mman.h> 4037420Scharnier#include <a.out.h> 4137420Scharnier#include <ctype.h> 421741Srich#include <dirent.h> 4376224Sobrien#include <elf-hints.h> 4437420Scharnier#include <err.h> 451741Srich#include <errno.h> 46696Spaul#include <fcntl.h> 47103436Speter#include <sys/link_aout.h> 481741Srich#include <stdio.h> 491741Srich#include <stdlib.h> 50696Spaul#include <string.h> 511741Srich#include <unistd.h> 52696Spaul 5338836Sjdp#include "ldconfig.h" 5418597Speter#include "shlib.h" 5518597Speter#include "support.h" 5618597Speter 5718859Sjdp#if DEBUG 5818859Sjdp/* test */ 5918859Sjdp#undef _PATH_LD_HINTS 6018859Sjdp#define _PATH_LD_HINTS "./ld.so.hints" 6138836Sjdp#undef _PATH_ELF_HINTS 6238836Sjdp#define _PATH_ELF_HINTS "./ld-elf.so.hints" 6318859Sjdp#endif 6418597Speter 65127250Speter#define _PATH_LD32_HINTS "/var/run/ld32.so.hints" 66127250Speter#define _PATH_ELF32_HINTS "/var/run/ld-elf32.so.hints" 67127250Speter 68696Spaul#undef major 69696Spaul#undef minor 70696Spaul 71696Spaulstatic int verbose; 72696Spaulstatic int nostd; 73696Spaulstatic int justread; 749290Sasamistatic int merge; 7528559Speterstatic int rescan; 76140241Sdelphijstatic const char *hints_file; 77696Spaul 78696Spaulstruct shlib_list { 79696Spaul /* Internal list of shared libraries found */ 80696Spaul char *name; 81696Spaul char *path; 82696Spaul int dewey[MAXDEWEY]; 83696Spaul int ndewey; 84696Spaul#define major dewey[0] 85696Spaul#define minor dewey[1] 86696Spaul struct shlib_list *next; 87696Spaul}; 88696Spaul 89696Spaulstatic struct shlib_list *shlib_head = NULL, **shlib_tail = &shlib_head; 9018597Speterstatic char *dir_list; 91696Spaul 9292882Simpstatic int buildhints(void); 9392882Simpstatic int dodir(char *, int); 9492882Simpint dofile(char *, int); 9592882Simpstatic void enter(char *, char *, char *, int *, int); 9692882Simpstatic void listhints(void); 9792882Simpstatic int readhints(void); 9892882Simpstatic void usage(void); 99696Spaul 100248525Simp/* 101248525Simp * Note on aout/a.out support. 102248525Simp * To properly support shared libraries for compat2x, which are a.out, we need 103248525Simp * to support a.out here. As of 2013, bug reports are still coming in for this 104248525Simp * feature (on amd64 no less), so we know it is still in use. 105248525Simp */ 106248525Simp 107696Spaulint 108140241Sdelphijmain(int argc, char **argv) 109696Spaul{ 110696Spaul int i, c; 111696Spaul int rval = 0; 112127250Speter int is_aout = 0; 113127250Speter int is_32 = 0; 114696Spaul 115127250Speter while (argc > 1) { 116127250Speter if (strcmp(argv[1], "-aout") == 0) { 117127250Speter is_aout = 1; 118127250Speter argc--; 119127250Speter argv++; 120127250Speter } else if (strcmp(argv[1], "-elf") == 0) { 121127250Speter is_aout = 0; 122127250Speter argc--; 123127250Speter argv++; 124127250Speter } else if (strcmp(argv[1], "-32") == 0) { 125127250Speter is_32 = 1; 126127250Speter argc--; 127127250Speter argv++; 128127250Speter } else { 129127250Speter break; 130127250Speter } 131103436Speter } 13238960Sjdp 133127250Speter if (is_32) 134127250Speter hints_file = is_aout ? _PATH_LD32_HINTS : _PATH_ELF32_HINTS; 135127250Speter else 136127250Speter hints_file = is_aout ? _PATH_LD_HINTS : _PATH_ELF_HINTS; 13762858Sjdp if (argc == 1) 13862858Sjdp rescan = 1; 13964360Sjdp else while((c = getopt(argc, argv, "Rf:imrsv")) != -1) { 140696Spaul switch (c) { 14128559Speter case 'R': 14228559Speter rescan = 1; 14328559Speter break; 14418859Sjdp case 'f': 14518859Sjdp hints_file = optarg; 14618859Sjdp break; 14764360Sjdp case 'i': 14864360Sjdp insecure = 1; 14964360Sjdp break; 1509290Sasami case 'm': 1519290Sasami merge = 1; 152696Spaul break; 1539290Sasami case 'r': 1549290Sasami justread = 1; 1559290Sasami break; 156696Spaul case 's': 157696Spaul nostd = 1; 158696Spaul break; 1599290Sasami case 'v': 1609290Sasami verbose = 1; 161696Spaul break; 162696Spaul default: 16337420Scharnier usage(); 164696Spaul break; 165696Spaul } 166696Spaul } 167696Spaul 16838960Sjdp if (!is_aout) { 16938836Sjdp if (justread) 17038836Sjdp list_elf_hints(hints_file); 17138836Sjdp else 17238836Sjdp update_elf_hints(hints_file, argc - optind, 17338836Sjdp argv + optind, merge || rescan); 17438836Sjdp return 0; 17538836Sjdp } 17638836Sjdp 17764360Sjdp /* Here begins the aout libs processing */ 17818597Speter dir_list = strdup(""); 17918597Speter 18028559Speter if (justread || merge || rescan) { 1819290Sasami if ((rval = readhints()) != 0) 1829290Sasami return rval; 1839290Sasami } 184696Spaul 18528559Speter if (!nostd && !merge && !rescan) 1861741Srich std_search_path(); 187696Spaul 18827334Sjkh /* Add any directories/files from the command line */ 18927334Sjkh if (!justread) { 19019522Sjdp for (i = optind; i < argc; i++) { 19127334Sjkh struct stat stbuf; 19227334Sjkh 19327334Sjkh if (stat(argv[i], &stbuf) == -1) { 19419522Sjdp warn("%s", argv[i]); 19519522Sjdp rval = -1; 19638885Sjdp } else if (strcmp(argv[i], "/usr/lib") == 0) { 19736397Ssos warnx("WARNING! '%s' can not be used", argv[i]); 19836397Ssos rval = -1; 19938885Sjdp } else { 20027334Sjkh /* 20127334Sjkh * See if this is a directory-containing 20227334Sjkh * file instead of a directory 20327334Sjkh */ 20427334Sjkh if (S_ISREG(stbuf.st_mode)) 20527334Sjkh rval |= dofile(argv[i], 0); 20627334Sjkh else 20727334Sjkh add_search_path(argv[i]); 20827334Sjkh } 20919522Sjdp } 21019522Sjdp } 21118597Speter 21218597Speter for (i = 0; i < n_search_dirs; i++) { 21318597Speter char *cp = concat(dir_list, *dir_list?":":"", search_dirs[i]); 21418597Speter free(dir_list); 21518597Speter dir_list = cp; 21618597Speter } 21718597Speter 21818597Speter if (justread) { 21918597Speter listhints(); 22018597Speter return 0; 22118597Speter } 22218597Speter 223696Spaul for (i = 0; i < n_search_dirs; i++) 2241153Sjkh rval |= dodir(search_dirs[i], 1); 225696Spaul 2269290Sasami rval |= buildhints(); 227696Spaul 228696Spaul return rval; 229696Spaul} 230696Spaul 23137420Scharnierstatic void 232201217Sedusage(void) 23337420Scharnier{ 23437420Scharnier fprintf(stderr, 235152323Sjhb "usage: ldconfig [-32] [-aout | -elf] [-Rimrsv] [-f hints_file] [directory | file ...]\n"); 23637420Scharnier exit(1); 23737420Scharnier} 23837420Scharnier 239696Spaulint 240201217Seddofile(char *fname, int silent) 24127334Sjkh{ 24227334Sjkh FILE *hfp; 24327334Sjkh char buf[MAXPATHLEN]; 24427334Sjkh int rval = 0; 24527334Sjkh char *cp, *sp; 24627334Sjkh 24727334Sjkh if ((hfp = fopen(fname, "r")) == NULL) { 24827334Sjkh warn("%s", fname); 24927334Sjkh return -1; 25027334Sjkh } 25127334Sjkh 25227334Sjkh while (fgets(buf, sizeof(buf), hfp)) { 25327334Sjkh cp = buf; 25427334Sjkh while (isspace(*cp)) 25527334Sjkh cp++; 25627334Sjkh if (*cp == '#' || *cp == '\0') 25727334Sjkh continue; 25827334Sjkh sp = cp; 25927334Sjkh while (!isspace(*cp) && *cp != '\0') 26027334Sjkh cp++; 26127334Sjkh 26227334Sjkh if (*cp != '\n') { 26327334Sjkh *cp = '\0'; 26437420Scharnier warnx("%s: trailing characters ignored", sp); 26527334Sjkh } 26627334Sjkh 26727334Sjkh *cp = '\0'; 26827334Sjkh 26927334Sjkh rval |= dodir(sp, silent); 27027334Sjkh } 27127334Sjkh 27227334Sjkh (void)fclose(hfp); 27327334Sjkh return rval; 27427334Sjkh} 27527334Sjkh 27627334Sjkhint 277201217Seddodir(char *dir, int silent) 278696Spaul{ 279696Spaul DIR *dd; 280696Spaul struct dirent *dp; 28114260Spst char name[MAXPATHLEN]; 282696Spaul int dewey[MAXDEWEY], ndewey; 283696Spaul 284696Spaul if ((dd = opendir(dir)) == NULL) { 28519522Sjdp if (silent && errno == ENOENT) /* Ignore the error */ 28619522Sjdp return 0; 28719522Sjdp warn("%s", dir); 288696Spaul return -1; 289696Spaul } 290696Spaul 291696Spaul while ((dp = readdir(dd)) != NULL) { 29292806Sobrien int n; 29392806Sobrien char *cp; 294696Spaul 29514260Spst /* Check for `lib' prefix */ 29614260Spst if (dp->d_name[0] != 'l' || 29714260Spst dp->d_name[1] != 'i' || 29814260Spst dp->d_name[2] != 'b') 29914260Spst continue; 300696Spaul 30114260Spst /* Copy the entry minus prefix */ 30214260Spst (void)strcpy(name, dp->d_name + 3); 30314260Spst n = strlen(name); 30414260Spst if (n < 4) 30514260Spst continue; 306696Spaul 30714260Spst /* Find ".so." in name */ 30814260Spst for (cp = name + n - 4; cp > name; --cp) { 30914260Spst if (cp[0] == '.' && 31014260Spst cp[1] == 's' && 31114260Spst cp[2] == 'o' && 31214260Spst cp[3] == '.') 31314260Spst break; 31414260Spst } 31514260Spst if (cp <= name) 316696Spaul continue; 317696Spaul 31814260Spst *cp = '\0'; 31914260Spst if (!isdigit(*(cp+4))) 32014260Spst continue; 32114260Spst 32214260Spst bzero((caddr_t)dewey, sizeof(dewey)); 32314260Spst ndewey = getdewey(dewey, cp + 4); 32438868Sjdp if (ndewey < 2) 32538868Sjdp continue; 326696Spaul enter(dir, dp->d_name, name, dewey, ndewey); 327696Spaul } 328696Spaul 32927334Sjkh closedir(dd); 330696Spaul return 0; 331696Spaul} 332696Spaul 333696Spaulstatic void 334201217Sedenter(char *dir, char *file, char *name, int dewey[], int ndewey) 335696Spaul{ 336696Spaul struct shlib_list *shp; 337696Spaul 338696Spaul for (shp = shlib_head; shp; shp = shp->next) { 339696Spaul if (strcmp(name, shp->name) != 0 || major != shp->major) 340696Spaul continue; 341696Spaul 342696Spaul /* Name matches existing entry */ 343696Spaul if (cmpndewey(dewey, ndewey, shp->dewey, shp->ndewey) > 0) { 344696Spaul 345696Spaul /* Update this entry with higher versioned lib */ 346696Spaul if (verbose) 347696Spaul printf("Updating lib%s.%d.%d to %s/%s\n", 348696Spaul shp->name, shp->major, shp->minor, 349696Spaul dir, file); 350696Spaul 351696Spaul free(shp->name); 352696Spaul shp->name = strdup(name); 353696Spaul free(shp->path); 354696Spaul shp->path = concat(dir, "/", file); 355696Spaul bcopy(dewey, shp->dewey, sizeof(shp->dewey)); 356696Spaul shp->ndewey = ndewey; 357696Spaul } 358696Spaul break; 359696Spaul } 360696Spaul 361696Spaul if (shp) 362696Spaul /* Name exists: older version or just updated */ 363696Spaul return; 364696Spaul 365696Spaul /* Allocate new list element */ 366696Spaul if (verbose) 367696Spaul printf("Adding %s/%s\n", dir, file); 368696Spaul 369696Spaul shp = (struct shlib_list *)xmalloc(sizeof *shp); 370696Spaul shp->name = strdup(name); 371696Spaul shp->path = concat(dir, "/", file); 372126896Scperciva bcopy(dewey, shp->dewey, sizeof(shp->dewey)); 373696Spaul shp->ndewey = ndewey; 374696Spaul shp->next = NULL; 375696Spaul 376696Spaul *shlib_tail = shp; 377696Spaul shlib_tail = &shp->next; 378696Spaul} 379696Spaul 380696Spaul 381140241Sdelphijstatic int 382140241Sdelphijhinthash(char *cp, int vmajor) 383696Spaul{ 384696Spaul int k = 0; 385696Spaul 386696Spaul while (*cp) 387696Spaul k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff; 388696Spaul 389696Spaul k = (((k << 1) + (k >> 14)) ^ (vmajor*257)) & 0x3fff; 390696Spaul 391696Spaul return k; 392696Spaul} 393696Spaul 394696Spaulint 395201217Sedbuildhints(void) 396696Spaul{ 397696Spaul struct hints_header hdr; 398696Spaul struct hints_bucket *blist; 399696Spaul struct shlib_list *shp; 400696Spaul char *strtab; 401696Spaul int i, n, str_index = 0; 402696Spaul int strtab_sz = 0; /* Total length of strings */ 403696Spaul int nhints = 0; /* Total number of hints */ 404696Spaul int fd; 405140244Sdelphij char *tmpfilename; 406696Spaul 407696Spaul for (shp = shlib_head; shp; shp = shp->next) { 408696Spaul strtab_sz += 1 + strlen(shp->name); 409696Spaul strtab_sz += 1 + strlen(shp->path); 410696Spaul nhints++; 411696Spaul } 412696Spaul 413696Spaul /* Fill hints file header */ 414696Spaul hdr.hh_magic = HH_MAGIC; 41518597Speter hdr.hh_version = LD_HINTS_VERSION_2; 416696Spaul hdr.hh_nbucket = 1 * nhints; 417696Spaul n = hdr.hh_nbucket * sizeof(struct hints_bucket); 418696Spaul hdr.hh_hashtab = sizeof(struct hints_header); 419696Spaul hdr.hh_strtab = hdr.hh_hashtab + n; 42018597Speter hdr.hh_dirlist = strtab_sz; 42118597Speter strtab_sz += 1 + strlen(dir_list); 422696Spaul hdr.hh_strtab_sz = strtab_sz; 423696Spaul hdr.hh_ehints = hdr.hh_strtab + hdr.hh_strtab_sz; 424696Spaul 425696Spaul if (verbose) 42617142Sjkh printf("Totals: entries %d, buckets %ld, string size %d\n", 42738023Sbde nhints, (long)hdr.hh_nbucket, strtab_sz); 428696Spaul 429696Spaul /* Allocate buckets and string table */ 430696Spaul blist = (struct hints_bucket *)xmalloc(n); 431696Spaul bzero((char *)blist, n); 432696Spaul for (i = 0; i < hdr.hh_nbucket; i++) 433696Spaul /* Empty all buckets */ 434696Spaul blist[i].hi_next = -1; 435696Spaul 436696Spaul strtab = (char *)xmalloc(strtab_sz); 437696Spaul 438696Spaul /* Enter all */ 439696Spaul for (shp = shlib_head; shp; shp = shp->next) { 440696Spaul struct hints_bucket *bp; 441696Spaul 442696Spaul bp = blist + 4435551Sjoerg (hinthash(shp->name, shp->major) % hdr.hh_nbucket); 444696Spaul 445696Spaul if (bp->hi_pathx) { 446140241Sdelphij int j; 447696Spaul 448140241Sdelphij for (j = 0; j < hdr.hh_nbucket; j++) { 449140241Sdelphij if (blist[j].hi_pathx == 0) 450696Spaul break; 451696Spaul } 452140241Sdelphij if (j == hdr.hh_nbucket) { 45337420Scharnier warnx("bummer!"); 454696Spaul return -1; 455696Spaul } 456696Spaul while (bp->hi_next != -1) 457696Spaul bp = &blist[bp->hi_next]; 458140241Sdelphij bp->hi_next = j; 459140241Sdelphij bp = blist + j; 460696Spaul } 461696Spaul 462696Spaul /* Insert strings in string table */ 463696Spaul bp->hi_namex = str_index; 464696Spaul strcpy(strtab + str_index, shp->name); 465696Spaul str_index += 1 + strlen(shp->name); 466696Spaul 467696Spaul bp->hi_pathx = str_index; 468696Spaul strcpy(strtab + str_index, shp->path); 469696Spaul str_index += 1 + strlen(shp->path); 470696Spaul 471696Spaul /* Copy versions */ 472696Spaul bcopy(shp->dewey, bp->hi_dewey, sizeof(bp->hi_dewey)); 473696Spaul bp->hi_ndewey = shp->ndewey; 474696Spaul } 475696Spaul 47618597Speter /* Copy search directories */ 47718597Speter strcpy(strtab + str_index, dir_list); 47818597Speter str_index += 1 + strlen(dir_list); 47918597Speter 48018597Speter /* Sanity check */ 48118597Speter if (str_index != strtab_sz) { 48218597Speter errx(1, "str_index(%d) != strtab_sz(%d)", str_index, strtab_sz); 48318597Speter } 48418597Speter 485140244Sdelphij tmpfilename = concat(hints_file, ".XXXXXXXXXX", ""); 48656125Skris umask(0); /* Create with exact permissions */ 487140244Sdelphij if ((fd = mkstemp(tmpfilename)) == -1) { 488140244Sdelphij warn("%s", tmpfilename); 48918597Speter return -1; 49018597Speter } 49156125Skris fchmod(fd, 0444); 49218597Speter 4931153Sjkh if (write(fd, &hdr, sizeof(struct hints_header)) != 4941153Sjkh sizeof(struct hints_header)) { 49518859Sjdp warn("%s", hints_file); 4961153Sjkh return -1; 4971153Sjkh } 498140248Sdelphij if (write(fd, blist, hdr.hh_nbucket * sizeof(*blist)) != 499140248Sdelphij (ssize_t)(hdr.hh_nbucket * sizeof(*blist))) { 50018859Sjdp warn("%s", hints_file); 5011153Sjkh return -1; 5021153Sjkh } 5031153Sjkh if (write(fd, strtab, strtab_sz) != strtab_sz) { 50418859Sjdp warn("%s", hints_file); 5051153Sjkh return -1; 5061153Sjkh } 507696Spaul if (close(fd) != 0) { 50818859Sjdp warn("%s", hints_file); 509696Spaul return -1; 510696Spaul } 511696Spaul 5121153Sjkh /* Install it */ 51318859Sjdp if (unlink(hints_file) != 0 && errno != ENOENT) { 51418859Sjdp warn("%s", hints_file); 515696Spaul return -1; 516696Spaul } 517696Spaul 518140244Sdelphij if (rename(tmpfilename, hints_file) != 0) { 51918859Sjdp warn("%s", hints_file); 520696Spaul return -1; 521696Spaul } 522696Spaul 523696Spaul return 0; 524696Spaul} 525696Spaul 5261741Srichstatic int 527201217Sedreadhints(void) 528696Spaul{ 529696Spaul int fd; 53038885Sjdp void *addr; 53138885Sjdp long fsize; 532696Spaul long msize; 533696Spaul struct hints_header *hdr; 534696Spaul struct hints_bucket *blist; 535696Spaul char *strtab; 5369290Sasami struct shlib_list *shp; 537696Spaul int i; 538696Spaul 53918859Sjdp if ((fd = open(hints_file, O_RDONLY, 0)) == -1) { 54018859Sjdp warn("%s", hints_file); 541696Spaul return -1; 542696Spaul } 543696Spaul 54418597Speter msize = PAGE_SIZE; 5455205Snate addr = mmap(0, msize, PROT_READ, MAP_COPY, fd, 0); 546696Spaul 54738885Sjdp if (addr == MAP_FAILED) { 54818859Sjdp warn("%s", hints_file); 549696Spaul return -1; 550696Spaul } 551696Spaul 552696Spaul hdr = (struct hints_header *)addr; 553696Spaul if (HH_BADMAG(*hdr)) { 55438023Sbde warnx("%s: bad magic: %lo", hints_file, 55538023Sbde (unsigned long)hdr->hh_magic); 556696Spaul return -1; 557696Spaul } 558696Spaul 55918597Speter if (hdr->hh_version != LD_HINTS_VERSION_1 && 56018597Speter hdr->hh_version != LD_HINTS_VERSION_2) { 56138023Sbde warnx("unsupported version: %ld", (long)hdr->hh_version); 562696Spaul return -1; 563696Spaul } 564696Spaul 565696Spaul if (hdr->hh_ehints > msize) { 56638885Sjdp fsize = hdr->hh_ehints; 56738885Sjdp munmap(addr, msize); 56838885Sjdp addr = mmap(0, fsize, PROT_READ, MAP_COPY, fd, 0); 56938885Sjdp if (addr == MAP_FAILED) { 57018859Sjdp warn("%s", hints_file); 571696Spaul return -1; 572696Spaul } 57338885Sjdp hdr = (struct hints_header *)addr; 574696Spaul } 575696Spaul close(fd); 576696Spaul 577133723Sstefanf strtab = (char *)addr + hdr->hh_strtab; 578696Spaul 57928559Speter if (hdr->hh_version >= LD_HINTS_VERSION_2) 58028559Speter add_search_path(strtab + hdr->hh_dirlist); 58128559Speter else if (rescan) 58228559Speter errx(1, "%s too old and does not contain the search path", 58328559Speter hints_file); 58428559Speter 58528559Speter if (rescan) 58628559Speter return 0; 58728559Speter 588140248Sdelphij blist = malloc(sizeof(*blist) * hdr->hh_nbucket); 589140241Sdelphij if (blist == NULL) 590140241Sdelphij err(1, "readhints"); 591140241Sdelphij memcpy(blist, (char *)addr + hdr->hh_hashtab, 592140248Sdelphij sizeof(*blist) * hdr->hh_nbucket); 593140241Sdelphij 594140241Sdelphij 595696Spaul for (i = 0; i < hdr->hh_nbucket; i++) { 596696Spaul struct hints_bucket *bp = &blist[i]; 597696Spaul 598696Spaul /* Sanity check */ 599696Spaul if (bp->hi_namex >= hdr->hh_strtab_sz) { 60037420Scharnier warnx("bad name index: %#x", bp->hi_namex); 601140241Sdelphij free(blist); 602696Spaul return -1; 603696Spaul } 604696Spaul if (bp->hi_pathx >= hdr->hh_strtab_sz) { 60537420Scharnier warnx("bad path index: %#x", bp->hi_pathx); 606140241Sdelphij free(blist); 607696Spaul return -1; 608696Spaul } 609696Spaul 6109290Sasami /* Allocate new list element */ 6119290Sasami shp = (struct shlib_list *)xmalloc(sizeof *shp); 6129290Sasami shp->name = strdup(strtab + bp->hi_namex); 6139290Sasami shp->path = strdup(strtab + bp->hi_pathx); 6149290Sasami bcopy(bp->hi_dewey, shp->dewey, sizeof(shp->dewey)); 6159290Sasami shp->ndewey = bp->hi_ndewey; 6169290Sasami shp->next = NULL; 6179290Sasami 6189290Sasami *shlib_tail = shp; 6199290Sasami shlib_tail = &shp->next; 620696Spaul } 621696Spaul 622140241Sdelphij free(blist); 623696Spaul return 0; 624696Spaul} 625696Spaul 6269290Sasamistatic void 627201217Sedlisthints(void) 6289290Sasami{ 6299290Sasami struct shlib_list *shp; 6309290Sasami int i; 6319290Sasami 63218859Sjdp printf("%s:\n", hints_file); 63318597Speter printf("\tsearch directories: %s\n", dir_list); 6349290Sasami 6359290Sasami for (i = 0, shp = shlib_head; shp; i++, shp = shp->next) 6369290Sasami printf("\t%d:-l%s.%d.%d => %s\n", 6379290Sasami i, shp->name, shp->major, shp->minor, shp->path); 6389290Sasami 6399290Sasami return; 6409290Sasami} 641