1b9ae52e3SPaul Richards /* 2b9ae52e3SPaul Richards * Copyright (c) 1993 Paul Kranenburg 3b9ae52e3SPaul Richards * All rights reserved. 4b9ae52e3SPaul Richards * 5b9ae52e3SPaul Richards * Redistribution and use in source and binary forms, with or without 6b9ae52e3SPaul Richards * modification, are permitted provided that the following conditions 7b9ae52e3SPaul Richards * are met: 8b9ae52e3SPaul Richards * 1. Redistributions of source code must retain the above copyright 9b9ae52e3SPaul Richards * notice, this list of conditions and the following disclaimer. 10b9ae52e3SPaul Richards * 2. Redistributions in binary form must reproduce the above copyright 11b9ae52e3SPaul Richards * notice, this list of conditions and the following disclaimer in the 12b9ae52e3SPaul Richards * documentation and/or other materials provided with the distribution. 13b9ae52e3SPaul Richards * 3. All advertising materials mentioning features or use of this software 14b9ae52e3SPaul Richards * must display the following acknowledgement: 15b9ae52e3SPaul Richards * This product includes software developed by Paul Kranenburg. 16b9ae52e3SPaul Richards * 4. The name of the author may not be used to endorse or promote products 17b9ae52e3SPaul Richards * derived from this software withough specific prior written permission 18b9ae52e3SPaul Richards * 19b9ae52e3SPaul Richards * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20b9ae52e3SPaul Richards * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21b9ae52e3SPaul Richards * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22b9ae52e3SPaul Richards * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23b9ae52e3SPaul Richards * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24b9ae52e3SPaul Richards * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25b9ae52e3SPaul Richards * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26b9ae52e3SPaul Richards * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27b9ae52e3SPaul Richards * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28b9ae52e3SPaul Richards * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29b9ae52e3SPaul Richards * 3052c4ca7aSJordan K. Hubbard * $Id: ldconfig.c,v 1.2 1993/11/09 04:19:22 paul Exp $ 31b9ae52e3SPaul Richards */ 32b9ae52e3SPaul Richards 33b9ae52e3SPaul Richards #include <sys/param.h> 34b9ae52e3SPaul Richards #include <stdio.h> 35b9ae52e3SPaul Richards #include <stdlib.h> 36b9ae52e3SPaul Richards #include <sys/types.h> 37b9ae52e3SPaul Richards #include <sys/stat.h> 38b9ae52e3SPaul Richards #include <sys/file.h> 39b9ae52e3SPaul Richards #include <sys/time.h> 40b9ae52e3SPaul Richards #include <sys/mman.h> 41b9ae52e3SPaul Richards #include <sys/resource.h> 42b9ae52e3SPaul Richards #include <fcntl.h> 43b9ae52e3SPaul Richards #include <errno.h> 44b9ae52e3SPaul Richards #include <ar.h> 45b9ae52e3SPaul Richards #include <ranlib.h> 46b9ae52e3SPaul Richards #include <a.out.h> 47b9ae52e3SPaul Richards #include <stab.h> 48b9ae52e3SPaul Richards #include <string.h> 49b9ae52e3SPaul Richards #include <dirent.h> 50b9ae52e3SPaul Richards 51b9ae52e3SPaul Richards #include "ld.h" 52b9ae52e3SPaul Richards 53b9ae52e3SPaul Richards #undef major 54b9ae52e3SPaul Richards #undef minor 55b9ae52e3SPaul Richards 56b9ae52e3SPaul Richards char *progname; 57b9ae52e3SPaul Richards static int verbose; 58b9ae52e3SPaul Richards static int nostd; 59b9ae52e3SPaul Richards static int justread; 60b9ae52e3SPaul Richards 61b9ae52e3SPaul Richards struct shlib_list { 62b9ae52e3SPaul Richards /* Internal list of shared libraries found */ 63b9ae52e3SPaul Richards char *name; 64b9ae52e3SPaul Richards char *path; 65b9ae52e3SPaul Richards int dewey[MAXDEWEY]; 66b9ae52e3SPaul Richards int ndewey; 67b9ae52e3SPaul Richards #define major dewey[0] 68b9ae52e3SPaul Richards #define minor dewey[1] 69b9ae52e3SPaul Richards struct shlib_list *next; 70b9ae52e3SPaul Richards }; 71b9ae52e3SPaul Richards 72b9ae52e3SPaul Richards static struct shlib_list *shlib_head = NULL, **shlib_tail = &shlib_head; 73b9ae52e3SPaul Richards 74b9ae52e3SPaul Richards static void enter __P((char *, char *, char *, int *, int)); 75b9ae52e3SPaul Richards static int dodir __P((char *)); 76b9ae52e3SPaul Richards static int build_hints __P((void)); 77b9ae52e3SPaul Richards 78b9ae52e3SPaul Richards int 79b9ae52e3SPaul Richards main(argc, argv) 80b9ae52e3SPaul Richards int argc; 81b9ae52e3SPaul Richards char *argv[]; 82b9ae52e3SPaul Richards { 83b9ae52e3SPaul Richards int i, c; 84b9ae52e3SPaul Richards int rval = 0; 85b9ae52e3SPaul Richards extern int optind; 86b9ae52e3SPaul Richards 87b9ae52e3SPaul Richards if ((progname = strrchr(argv[0], '/')) == NULL) 88b9ae52e3SPaul Richards progname = argv[0]; 89b9ae52e3SPaul Richards else 90b9ae52e3SPaul Richards progname++; 91b9ae52e3SPaul Richards 92b9ae52e3SPaul Richards while ((c = getopt(argc, argv, "rsv")) != EOF) { 93b9ae52e3SPaul Richards switch (c) { 94b9ae52e3SPaul Richards case 'v': 95b9ae52e3SPaul Richards verbose = 1; 96b9ae52e3SPaul Richards break; 97b9ae52e3SPaul Richards case 's': 98b9ae52e3SPaul Richards nostd = 1; 99b9ae52e3SPaul Richards break; 100b9ae52e3SPaul Richards case 'r': 101b9ae52e3SPaul Richards justread = 1; 102b9ae52e3SPaul Richards break; 103b9ae52e3SPaul Richards default: 104b9ae52e3SPaul Richards fprintf(stderr, "Usage: %s [-v] [dir ...]\n", progname); 105b9ae52e3SPaul Richards exit(1); 106b9ae52e3SPaul Richards break; 107b9ae52e3SPaul Richards } 108b9ae52e3SPaul Richards } 109b9ae52e3SPaul Richards 110b9ae52e3SPaul Richards if (justread) 111b9ae52e3SPaul Richards return listhints(); 112b9ae52e3SPaul Richards 113b9ae52e3SPaul Richards if (!nostd) 114b9ae52e3SPaul Richards std_search_dirs(NULL); 115b9ae52e3SPaul Richards 116b9ae52e3SPaul Richards for (i = 0; i < n_search_dirs; i++) 117b9ae52e3SPaul Richards rval |= dodir(search_dirs[i]); 118b9ae52e3SPaul Richards 119b9ae52e3SPaul Richards for (i = optind; i < argc; i++) 120b9ae52e3SPaul Richards rval |= dodir(argv[i]); 121b9ae52e3SPaul Richards 122b9ae52e3SPaul Richards rval |= build_hints(); 123b9ae52e3SPaul Richards 124b9ae52e3SPaul Richards return rval; 125b9ae52e3SPaul Richards } 126b9ae52e3SPaul Richards 127b9ae52e3SPaul Richards int 128b9ae52e3SPaul Richards dodir(dir) 129b9ae52e3SPaul Richards char *dir; 130b9ae52e3SPaul Richards { 131b9ae52e3SPaul Richards DIR *dd; 132b9ae52e3SPaul Richards struct dirent *dp; 133b9ae52e3SPaul Richards char name[MAXPATHLEN], rest[MAXPATHLEN]; 134b9ae52e3SPaul Richards int dewey[MAXDEWEY], ndewey; 135b9ae52e3SPaul Richards 136b9ae52e3SPaul Richards if ((dd = opendir(dir)) == NULL) { 137b9ae52e3SPaul Richards perror(dir); 138b9ae52e3SPaul Richards return -1; 139b9ae52e3SPaul Richards } 140b9ae52e3SPaul Richards 141b9ae52e3SPaul Richards while ((dp = readdir(dd)) != NULL) { 142b9ae52e3SPaul Richards int n; 143b9ae52e3SPaul Richards 144b9ae52e3SPaul Richards name[0] = rest[0] = '\0'; 145b9ae52e3SPaul Richards 146b9ae52e3SPaul Richards n = sscanf(dp->d_name, "lib%[^.].so.%s", 147b9ae52e3SPaul Richards name, rest); 148b9ae52e3SPaul Richards 149b9ae52e3SPaul Richards if (n < 2 || rest[0] == '\0') 150b9ae52e3SPaul Richards continue; 151b9ae52e3SPaul Richards 152b9ae52e3SPaul Richards ndewey = getdewey(dewey, rest); 153b9ae52e3SPaul Richards enter(dir, dp->d_name, name, dewey, ndewey); 154b9ae52e3SPaul Richards } 155b9ae52e3SPaul Richards 156b9ae52e3SPaul Richards return 0; 157b9ae52e3SPaul Richards } 158b9ae52e3SPaul Richards 159b9ae52e3SPaul Richards static void 160b9ae52e3SPaul Richards enter(dir, file, name, dewey, ndewey) 161b9ae52e3SPaul Richards char *dir, *file, *name; 162b9ae52e3SPaul Richards int dewey[], ndewey; 163b9ae52e3SPaul Richards { 164b9ae52e3SPaul Richards struct shlib_list *shp; 165b9ae52e3SPaul Richards 166b9ae52e3SPaul Richards for (shp = shlib_head; shp; shp = shp->next) { 167b9ae52e3SPaul Richards if (strcmp(name, shp->name) != 0 || major != shp->major) 168b9ae52e3SPaul Richards continue; 169b9ae52e3SPaul Richards 170b9ae52e3SPaul Richards /* Name matches existing entry */ 171b9ae52e3SPaul Richards if (cmpndewey(dewey, ndewey, shp->dewey, shp->ndewey) > 0) { 172b9ae52e3SPaul Richards 173b9ae52e3SPaul Richards /* Update this entry with higher versioned lib */ 174b9ae52e3SPaul Richards if (verbose) 175b9ae52e3SPaul Richards printf("Updating lib%s.%d.%d to %s/%s\n", 176b9ae52e3SPaul Richards shp->name, shp->major, shp->minor, 177b9ae52e3SPaul Richards dir, file); 178b9ae52e3SPaul Richards 179b9ae52e3SPaul Richards free(shp->name); 180b9ae52e3SPaul Richards shp->name = strdup(name); 181b9ae52e3SPaul Richards free(shp->path); 182b9ae52e3SPaul Richards shp->path = concat(dir, "/", file); 183b9ae52e3SPaul Richards bcopy(dewey, shp->dewey, sizeof(shp->dewey)); 184b9ae52e3SPaul Richards shp->ndewey = ndewey; 185b9ae52e3SPaul Richards } 186b9ae52e3SPaul Richards break; 187b9ae52e3SPaul Richards } 188b9ae52e3SPaul Richards 189b9ae52e3SPaul Richards if (shp) 190b9ae52e3SPaul Richards /* Name exists: older version or just updated */ 191b9ae52e3SPaul Richards return; 192b9ae52e3SPaul Richards 193b9ae52e3SPaul Richards /* Allocate new list element */ 194b9ae52e3SPaul Richards if (verbose) 195b9ae52e3SPaul Richards printf("Adding %s/%s\n", dir, file); 196b9ae52e3SPaul Richards 197b9ae52e3SPaul Richards shp = (struct shlib_list *)xmalloc(sizeof *shp); 198b9ae52e3SPaul Richards shp->name = strdup(name); 199b9ae52e3SPaul Richards shp->path = concat(dir, "/", file); 200b9ae52e3SPaul Richards bcopy(dewey, shp->dewey, MAXDEWEY); 201b9ae52e3SPaul Richards shp->ndewey = ndewey; 202b9ae52e3SPaul Richards shp->next = NULL; 203b9ae52e3SPaul Richards 204b9ae52e3SPaul Richards *shlib_tail = shp; 205b9ae52e3SPaul Richards shlib_tail = &shp->next; 206b9ae52e3SPaul Richards } 207b9ae52e3SPaul Richards 208b9ae52e3SPaul Richards 209b9ae52e3SPaul Richards #if DEBUG 210b9ae52e3SPaul Richards /* test */ 211b9ae52e3SPaul Richards #undef _PATH_LD_HINTS 212b9ae52e3SPaul Richards #define _PATH_LD_HINTS "./ld.so.hints" 213b9ae52e3SPaul Richards #endif 214b9ae52e3SPaul Richards 215b9ae52e3SPaul Richards int 216b9ae52e3SPaul Richards hinthash(cp, vmajor, vminor) 217b9ae52e3SPaul Richards char *cp; 218b9ae52e3SPaul Richards int vmajor, vminor; 219b9ae52e3SPaul Richards { 220b9ae52e3SPaul Richards int k = 0; 221b9ae52e3SPaul Richards 222b9ae52e3SPaul Richards while (*cp) 223b9ae52e3SPaul Richards k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff; 224b9ae52e3SPaul Richards 225b9ae52e3SPaul Richards k = (((k << 1) + (k >> 14)) ^ (vmajor*257)) & 0x3fff; 226b9ae52e3SPaul Richards k = (((k << 1) + (k >> 14)) ^ (vminor*167)) & 0x3fff; 227b9ae52e3SPaul Richards 228b9ae52e3SPaul Richards return k; 229b9ae52e3SPaul Richards } 230b9ae52e3SPaul Richards 231b9ae52e3SPaul Richards int 232b9ae52e3SPaul Richards build_hints() 233b9ae52e3SPaul Richards { 234b9ae52e3SPaul Richards struct hints_header hdr; 235b9ae52e3SPaul Richards struct hints_bucket *blist; 236b9ae52e3SPaul Richards struct shlib_list *shp; 237b9ae52e3SPaul Richards char *strtab; 238b9ae52e3SPaul Richards int i, n, str_index = 0; 239b9ae52e3SPaul Richards int strtab_sz = 0; /* Total length of strings */ 240b9ae52e3SPaul Richards int nhints = 0; /* Total number of hints */ 241b9ae52e3SPaul Richards int fd; 242b9ae52e3SPaul Richards char *tmpfile; 243b9ae52e3SPaul Richards 244b9ae52e3SPaul Richards for (shp = shlib_head; shp; shp = shp->next) { 245b9ae52e3SPaul Richards strtab_sz += 1 + strlen(shp->name); 246b9ae52e3SPaul Richards strtab_sz += 1 + strlen(shp->path); 247b9ae52e3SPaul Richards nhints++; 248b9ae52e3SPaul Richards } 249b9ae52e3SPaul Richards 250b9ae52e3SPaul Richards /* Fill hints file header */ 251b9ae52e3SPaul Richards hdr.hh_magic = HH_MAGIC; 252b9ae52e3SPaul Richards hdr.hh_version = LD_HINTS_VERSION_1; 253b9ae52e3SPaul Richards hdr.hh_nbucket = 1 * nhints; 254b9ae52e3SPaul Richards n = hdr.hh_nbucket * sizeof(struct hints_bucket); 255b9ae52e3SPaul Richards hdr.hh_hashtab = sizeof(struct hints_header); 256b9ae52e3SPaul Richards hdr.hh_strtab = hdr.hh_hashtab + n; 257b9ae52e3SPaul Richards hdr.hh_strtab_sz = strtab_sz; 258b9ae52e3SPaul Richards hdr.hh_ehints = hdr.hh_strtab + hdr.hh_strtab_sz; 259b9ae52e3SPaul Richards 260b9ae52e3SPaul Richards if (verbose) 261b9ae52e3SPaul Richards printf("Totals: entries %d, buckets %d, string size %d\n", 262b9ae52e3SPaul Richards nhints, hdr.hh_nbucket, strtab_sz); 263b9ae52e3SPaul Richards 264b9ae52e3SPaul Richards /* Allocate buckets and string table */ 265b9ae52e3SPaul Richards blist = (struct hints_bucket *)xmalloc(n); 266b9ae52e3SPaul Richards bzero((char *)blist, n); 267b9ae52e3SPaul Richards for (i = 0; i < hdr.hh_nbucket; i++) 268b9ae52e3SPaul Richards /* Empty all buckets */ 269b9ae52e3SPaul Richards blist[i].hi_next = -1; 270b9ae52e3SPaul Richards 271b9ae52e3SPaul Richards strtab = (char *)xmalloc(strtab_sz); 272b9ae52e3SPaul Richards 273b9ae52e3SPaul Richards /* Enter all */ 274b9ae52e3SPaul Richards for (shp = shlib_head; shp; shp = shp->next) { 275b9ae52e3SPaul Richards struct hints_bucket *bp; 276b9ae52e3SPaul Richards 277b9ae52e3SPaul Richards bp = blist + 278b9ae52e3SPaul Richards (hinthash(shp->name, shp->major, shp->minor) % hdr.hh_nbucket); 279b9ae52e3SPaul Richards 280b9ae52e3SPaul Richards if (bp->hi_pathx) { 281b9ae52e3SPaul Richards int i; 282b9ae52e3SPaul Richards 283b9ae52e3SPaul Richards for (i = 0; i < hdr.hh_nbucket; i++) { 284b9ae52e3SPaul Richards if (blist[i].hi_pathx == 0) 285b9ae52e3SPaul Richards break; 286b9ae52e3SPaul Richards } 287b9ae52e3SPaul Richards if (i == hdr.hh_nbucket) { 288b9ae52e3SPaul Richards fprintf(stderr, "Bummer!\n"); 289b9ae52e3SPaul Richards return -1; 290b9ae52e3SPaul Richards } 291b9ae52e3SPaul Richards while (bp->hi_next != -1) 292b9ae52e3SPaul Richards bp = &blist[bp->hi_next]; 293b9ae52e3SPaul Richards bp->hi_next = i; 294b9ae52e3SPaul Richards bp = blist + i; 295b9ae52e3SPaul Richards } 296b9ae52e3SPaul Richards 297b9ae52e3SPaul Richards /* Insert strings in string table */ 298b9ae52e3SPaul Richards bp->hi_namex = str_index; 299b9ae52e3SPaul Richards strcpy(strtab + str_index, shp->name); 300b9ae52e3SPaul Richards str_index += 1 + strlen(shp->name); 301b9ae52e3SPaul Richards 302b9ae52e3SPaul Richards bp->hi_pathx = str_index; 303b9ae52e3SPaul Richards strcpy(strtab + str_index, shp->path); 304b9ae52e3SPaul Richards str_index += 1 + strlen(shp->path); 305b9ae52e3SPaul Richards 306b9ae52e3SPaul Richards /* Copy versions */ 307b9ae52e3SPaul Richards bcopy(shp->dewey, bp->hi_dewey, sizeof(bp->hi_dewey)); 308b9ae52e3SPaul Richards bp->hi_ndewey = shp->ndewey; 309b9ae52e3SPaul Richards } 310b9ae52e3SPaul Richards 311b9ae52e3SPaul Richards tmpfile = concat(_PATH_LD_HINTS, "+", ""); 312b9ae52e3SPaul Richards if ((fd = open(tmpfile, O_RDWR|O_CREAT|O_TRUNC, 0444)) == -1) { 313b9ae52e3SPaul Richards perror(_PATH_LD_HINTS); 314b9ae52e3SPaul Richards return -1; 315b9ae52e3SPaul Richards } 316b9ae52e3SPaul Richards 317b9ae52e3SPaul Richards mywrite(&hdr, 1, sizeof(struct hints_header), fd); 318b9ae52e3SPaul Richards mywrite(blist, hdr.hh_nbucket, sizeof(struct hints_bucket), fd); 319b9ae52e3SPaul Richards mywrite(strtab, strtab_sz, 1, fd); 320b9ae52e3SPaul Richards 321b9ae52e3SPaul Richards if (close(fd) != 0) { 322b9ae52e3SPaul Richards perror(_PATH_LD_HINTS); 323b9ae52e3SPaul Richards return -1; 324b9ae52e3SPaul Richards } 325b9ae52e3SPaul Richards 326b9ae52e3SPaul Richards /* Now, install real file */ 327b9ae52e3SPaul Richards if (unlink(_PATH_LD_HINTS) != 0 && errno != ENOENT) { 328b9ae52e3SPaul Richards perror(_PATH_LD_HINTS); 329b9ae52e3SPaul Richards return -1; 330b9ae52e3SPaul Richards } 331b9ae52e3SPaul Richards 332b9ae52e3SPaul Richards if (rename(tmpfile, _PATH_LD_HINTS) != 0) { 333b9ae52e3SPaul Richards perror(_PATH_LD_HINTS); 334b9ae52e3SPaul Richards return -1; 335b9ae52e3SPaul Richards } 336b9ae52e3SPaul Richards 337b9ae52e3SPaul Richards return 0; 338b9ae52e3SPaul Richards } 339b9ae52e3SPaul Richards 340b9ae52e3SPaul Richards int 341b9ae52e3SPaul Richards listhints() 342b9ae52e3SPaul Richards { 343b9ae52e3SPaul Richards int fd; 344b9ae52e3SPaul Richards caddr_t addr; 345b9ae52e3SPaul Richards long msize; 346b9ae52e3SPaul Richards struct hints_header *hdr; 347b9ae52e3SPaul Richards struct hints_bucket *blist; 348b9ae52e3SPaul Richards char *strtab; 349b9ae52e3SPaul Richards int i; 350b9ae52e3SPaul Richards 351b9ae52e3SPaul Richards if ((fd = open(_PATH_LD_HINTS, O_RDONLY, 0)) == -1) { 352b9ae52e3SPaul Richards perror(_PATH_LD_HINTS); 353b9ae52e3SPaul Richards return -1; 354b9ae52e3SPaul Richards } 355b9ae52e3SPaul Richards 356b9ae52e3SPaul Richards msize = PAGSIZ; 357b9ae52e3SPaul Richards addr = mmap(0, msize, PROT_READ, MAP_FILE|MAP_COPY, fd, 0); 358b9ae52e3SPaul Richards 359b9ae52e3SPaul Richards if (addr == (caddr_t)-1) { 360b9ae52e3SPaul Richards perror(_PATH_LD_HINTS); 361b9ae52e3SPaul Richards return -1; 362b9ae52e3SPaul Richards } 363b9ae52e3SPaul Richards 364b9ae52e3SPaul Richards hdr = (struct hints_header *)addr; 365b9ae52e3SPaul Richards if (HH_BADMAG(*hdr)) { 366b9ae52e3SPaul Richards fprintf(stderr, "%s: Bad magic: %d\n"); 367b9ae52e3SPaul Richards return -1; 368b9ae52e3SPaul Richards } 369b9ae52e3SPaul Richards 370b9ae52e3SPaul Richards if (hdr->hh_version != LD_HINTS_VERSION_1) { 371b9ae52e3SPaul Richards fprintf(stderr, "Unsupported version: %d\n", hdr->hh_version); 372b9ae52e3SPaul Richards return -1; 373b9ae52e3SPaul Richards } 374b9ae52e3SPaul Richards 375b9ae52e3SPaul Richards if (hdr->hh_ehints > msize) { 376b9ae52e3SPaul Richards if (mmap(addr+msize, hdr->hh_ehints - msize, 377b9ae52e3SPaul Richards PROT_READ, MAP_FILE|MAP_COPY|MAP_FIXED, 378b9ae52e3SPaul Richards fd, msize) != (caddr_t)(addr+msize)) { 379b9ae52e3SPaul Richards 380b9ae52e3SPaul Richards perror(_PATH_LD_HINTS); 381b9ae52e3SPaul Richards return -1; 382b9ae52e3SPaul Richards } 383b9ae52e3SPaul Richards } 384b9ae52e3SPaul Richards close(fd); 385b9ae52e3SPaul Richards 386b9ae52e3SPaul Richards blist = (struct hints_bucket *)(addr + hdr->hh_hashtab); 387b9ae52e3SPaul Richards strtab = (char *)(addr + hdr->hh_strtab); 388b9ae52e3SPaul Richards 389b9ae52e3SPaul Richards printf("%s:\n", _PATH_LD_HINTS); 390b9ae52e3SPaul Richards for (i = 0; i < hdr->hh_nbucket; i++) { 391b9ae52e3SPaul Richards struct hints_bucket *bp = &blist[i]; 392b9ae52e3SPaul Richards 393b9ae52e3SPaul Richards /* Sanity check */ 394b9ae52e3SPaul Richards if (bp->hi_namex >= hdr->hh_strtab_sz) { 395b9ae52e3SPaul Richards fprintf(stderr, "Bad name index: %#x\n", bp->hi_namex); 396b9ae52e3SPaul Richards return -1; 397b9ae52e3SPaul Richards } 398b9ae52e3SPaul Richards if (bp->hi_pathx >= hdr->hh_strtab_sz) { 399b9ae52e3SPaul Richards fprintf(stderr, "Bad path index: %#x\n", bp->hi_pathx); 400b9ae52e3SPaul Richards return -1; 401b9ae52e3SPaul Richards } 402b9ae52e3SPaul Richards 40352c4ca7aSJordan K. Hubbard printf("\t%d:-l%s.%d.%d => %s (%d -> %d)\n", 40452c4ca7aSJordan K. Hubbard i, 405b9ae52e3SPaul Richards strtab + bp->hi_namex, bp->hi_major, bp->hi_minor, 40652c4ca7aSJordan K. Hubbard strtab + bp->hi_pathx, 40752c4ca7aSJordan K. Hubbard hinthash(strtab+bp->hi_namex, bp->hi_major, bp->hi_minor) 40852c4ca7aSJordan K. Hubbard % hdr->hh_nbucket, 40952c4ca7aSJordan K. Hubbard bp->hi_next); 410b9ae52e3SPaul Richards } 411b9ae52e3SPaul Richards 412b9ae52e3SPaul Richards return 0; 413b9ae52e3SPaul Richards } 414b9ae52e3SPaul Richards 415