1b9ae52e3SPaul Richards /* 20f6b2cb3SPaul Traina * Copyright (c) 1993,1995 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 1709e3d49dSJordan K. Hubbard * derived from this software without 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 * 30526195adSJordan K. Hubbard * $Id: ldconfig.c,v 1.12 1996/02/26 02:22:33 pst Exp $ 31b9ae52e3SPaul Richards */ 32b9ae52e3SPaul Richards 33b9ae52e3SPaul Richards #include <sys/param.h> 34b9ae52e3SPaul Richards #include <sys/types.h> 35b9ae52e3SPaul Richards #include <sys/stat.h> 36b9ae52e3SPaul Richards #include <sys/file.h> 37b9ae52e3SPaul Richards #include <sys/time.h> 38b9ae52e3SPaul Richards #include <sys/mman.h> 39b9ae52e3SPaul Richards #include <sys/resource.h> 40699e1b82SRich Murphey #include <dirent.h> 41b9ae52e3SPaul Richards #include <errno.h> 42526195adSJordan K. Hubbard #include <err.h> 43526195adSJordan K. Hubbard #include <ctype.h> 44699e1b82SRich Murphey #include <fcntl.h> 45b9ae52e3SPaul Richards #include <ar.h> 46b9ae52e3SPaul Richards #include <ranlib.h> 47b9ae52e3SPaul Richards #include <a.out.h> 48b9ae52e3SPaul Richards #include <stab.h> 49699e1b82SRich Murphey #include <stdio.h> 50699e1b82SRich Murphey #include <stdlib.h> 51b9ae52e3SPaul Richards #include <string.h> 52699e1b82SRich Murphey #include <unistd.h> 53b9ae52e3SPaul Richards 54b9ae52e3SPaul Richards #include "ld.h" 55b9ae52e3SPaul Richards 56b9ae52e3SPaul Richards #undef major 57b9ae52e3SPaul Richards #undef minor 58b9ae52e3SPaul Richards 5961f9ce8dSNate Williams extern char *__progname; 6061f9ce8dSNate Williams 61b9ae52e3SPaul Richards static int verbose; 62b9ae52e3SPaul Richards static int nostd; 63b9ae52e3SPaul Richards static int justread; 64f606c848SSatoshi Asami static int merge; 65b9ae52e3SPaul Richards 66b9ae52e3SPaul Richards struct shlib_list { 67b9ae52e3SPaul Richards /* Internal list of shared libraries found */ 68b9ae52e3SPaul Richards char *name; 69b9ae52e3SPaul Richards char *path; 70b9ae52e3SPaul Richards int dewey[MAXDEWEY]; 71b9ae52e3SPaul Richards int ndewey; 72b9ae52e3SPaul Richards #define major dewey[0] 73b9ae52e3SPaul Richards #define minor dewey[1] 74b9ae52e3SPaul Richards struct shlib_list *next; 75b9ae52e3SPaul Richards }; 76b9ae52e3SPaul Richards 77b9ae52e3SPaul Richards static struct shlib_list *shlib_head = NULL, **shlib_tail = &shlib_head; 78b9ae52e3SPaul Richards 79b9ae52e3SPaul Richards static void enter __P((char *, char *, char *, int *, int)); 8009e3d49dSJordan K. Hubbard static int dodir __P((char *, int)); 81f606c848SSatoshi Asami static int buildhints __P((void)); 82f606c848SSatoshi Asami static int readhints __P((void)); 83f606c848SSatoshi Asami static void listhints __P((void)); 84b9ae52e3SPaul Richards 85b9ae52e3SPaul Richards int 86b9ae52e3SPaul Richards main(argc, argv) 87b9ae52e3SPaul Richards int argc; 88b9ae52e3SPaul Richards char *argv[]; 89b9ae52e3SPaul Richards { 90b9ae52e3SPaul Richards int i, c; 91b9ae52e3SPaul Richards int rval = 0; 92b9ae52e3SPaul Richards 93f606c848SSatoshi Asami while ((c = getopt(argc, argv, "mrsv")) != EOF) { 94b9ae52e3SPaul Richards switch (c) { 95f606c848SSatoshi Asami case 'm': 96f606c848SSatoshi Asami merge = 1; 97b9ae52e3SPaul Richards break; 98b9ae52e3SPaul Richards case 'r': 99b9ae52e3SPaul Richards justread = 1; 100b9ae52e3SPaul Richards break; 101f606c848SSatoshi Asami case 's': 102f606c848SSatoshi Asami nostd = 1; 103f606c848SSatoshi Asami break; 104f606c848SSatoshi Asami case 'v': 105f606c848SSatoshi Asami verbose = 1; 106f606c848SSatoshi Asami break; 107b9ae52e3SPaul Richards default: 108f606c848SSatoshi Asami errx(1, "Usage: %s [-m][-r][-s][-v][dir ...]", 10961f9ce8dSNate Williams __progname); 110b9ae52e3SPaul Richards break; 111b9ae52e3SPaul Richards } 112b9ae52e3SPaul Richards } 113b9ae52e3SPaul Richards 114f606c848SSatoshi Asami if (justread || merge) { 115f606c848SSatoshi Asami if ((rval = readhints()) != 0) 116f606c848SSatoshi Asami return rval; 117f606c848SSatoshi Asami if (justread) { 118f606c848SSatoshi Asami listhints(); 119526195adSJordan K. Hubbard return 0; 120f606c848SSatoshi Asami } 121f606c848SSatoshi Asami } 122b9ae52e3SPaul Richards 123b9ae52e3SPaul Richards if (!nostd) 124699e1b82SRich Murphey std_search_path(); 125b9ae52e3SPaul Richards 126b9ae52e3SPaul Richards for (i = 0; i < n_search_dirs; i++) 12709e3d49dSJordan K. Hubbard rval |= dodir(search_dirs[i], 1); 128b9ae52e3SPaul Richards 129b9ae52e3SPaul Richards for (i = optind; i < argc; i++) 13009e3d49dSJordan K. Hubbard rval |= dodir(argv[i], 0); 131b9ae52e3SPaul Richards 132f606c848SSatoshi Asami rval |= buildhints(); 133b9ae52e3SPaul Richards 134b9ae52e3SPaul Richards return rval; 135b9ae52e3SPaul Richards } 136b9ae52e3SPaul Richards 137b9ae52e3SPaul Richards int 13809e3d49dSJordan K. Hubbard dodir(dir, silent) 139b9ae52e3SPaul Richards char *dir; 14009e3d49dSJordan K. Hubbard int silent; 141b9ae52e3SPaul Richards { 142b9ae52e3SPaul Richards DIR *dd; 143b9ae52e3SPaul Richards struct dirent *dp; 1440f6b2cb3SPaul Traina char name[MAXPATHLEN]; 145b9ae52e3SPaul Richards int dewey[MAXDEWEY], ndewey; 146b9ae52e3SPaul Richards 147b9ae52e3SPaul Richards if ((dd = opendir(dir)) == NULL) { 14809e3d49dSJordan K. Hubbard if (!silent || errno != ENOENT) 149f606c848SSatoshi Asami warn("%s", dir); 150b9ae52e3SPaul Richards return -1; 151b9ae52e3SPaul Richards } 152b9ae52e3SPaul Richards 153b9ae52e3SPaul Richards while ((dp = readdir(dd)) != NULL) { 1540f6b2cb3SPaul Traina register int n; 1550f6b2cb3SPaul Traina register char *cp; 156b9ae52e3SPaul Richards 1570f6b2cb3SPaul Traina /* Check for `lib' prefix */ 1580f6b2cb3SPaul Traina if (dp->d_name[0] != 'l' || 1590f6b2cb3SPaul Traina dp->d_name[1] != 'i' || 1600f6b2cb3SPaul Traina dp->d_name[2] != 'b') 161b9ae52e3SPaul Richards continue; 162b9ae52e3SPaul Richards 1630f6b2cb3SPaul Traina /* Copy the entry minus prefix */ 1640f6b2cb3SPaul Traina (void)strcpy(name, dp->d_name + 3); 1650f6b2cb3SPaul Traina n = strlen(name); 1660f6b2cb3SPaul Traina if (n < 4) 1670f6b2cb3SPaul Traina continue; 1680f6b2cb3SPaul Traina 1690f6b2cb3SPaul Traina /* Find ".so." in name */ 1700f6b2cb3SPaul Traina for (cp = name + n - 4; cp > name; --cp) { 1710f6b2cb3SPaul Traina if (cp[0] == '.' && 1720f6b2cb3SPaul Traina cp[1] == 's' && 1730f6b2cb3SPaul Traina cp[2] == 'o' && 1740f6b2cb3SPaul Traina cp[3] == '.') 1750f6b2cb3SPaul Traina break; 1760f6b2cb3SPaul Traina } 1770f6b2cb3SPaul Traina if (cp <= name) 1780f6b2cb3SPaul Traina continue; 1790f6b2cb3SPaul Traina 1800f6b2cb3SPaul Traina *cp = '\0'; 1810f6b2cb3SPaul Traina if (!isdigit(*(cp+4))) 1820f6b2cb3SPaul Traina continue; 1830f6b2cb3SPaul Traina 1840f6b2cb3SPaul Traina bzero((caddr_t)dewey, sizeof(dewey)); 1850f6b2cb3SPaul Traina ndewey = getdewey(dewey, cp + 4); 186b9ae52e3SPaul Richards enter(dir, dp->d_name, name, dewey, ndewey); 187b9ae52e3SPaul Richards } 188b9ae52e3SPaul Richards 189b9ae52e3SPaul Richards return 0; 190b9ae52e3SPaul Richards } 191b9ae52e3SPaul Richards 192b9ae52e3SPaul Richards static void 193b9ae52e3SPaul Richards enter(dir, file, name, dewey, ndewey) 194b9ae52e3SPaul Richards char *dir, *file, *name; 195b9ae52e3SPaul Richards int dewey[], ndewey; 196b9ae52e3SPaul Richards { 197b9ae52e3SPaul Richards struct shlib_list *shp; 198b9ae52e3SPaul Richards 199b9ae52e3SPaul Richards for (shp = shlib_head; shp; shp = shp->next) { 200b9ae52e3SPaul Richards if (strcmp(name, shp->name) != 0 || major != shp->major) 201b9ae52e3SPaul Richards continue; 202b9ae52e3SPaul Richards 203b9ae52e3SPaul Richards /* Name matches existing entry */ 204b9ae52e3SPaul Richards if (cmpndewey(dewey, ndewey, shp->dewey, shp->ndewey) > 0) { 205b9ae52e3SPaul Richards 206b9ae52e3SPaul Richards /* Update this entry with higher versioned lib */ 207b9ae52e3SPaul Richards if (verbose) 208b9ae52e3SPaul Richards printf("Updating lib%s.%d.%d to %s/%s\n", 209b9ae52e3SPaul Richards shp->name, shp->major, shp->minor, 210b9ae52e3SPaul Richards dir, file); 211b9ae52e3SPaul Richards 212b9ae52e3SPaul Richards free(shp->name); 213b9ae52e3SPaul Richards shp->name = strdup(name); 214b9ae52e3SPaul Richards free(shp->path); 215b9ae52e3SPaul Richards shp->path = concat(dir, "/", file); 216b9ae52e3SPaul Richards bcopy(dewey, shp->dewey, sizeof(shp->dewey)); 217b9ae52e3SPaul Richards shp->ndewey = ndewey; 218b9ae52e3SPaul Richards } 219b9ae52e3SPaul Richards break; 220b9ae52e3SPaul Richards } 221b9ae52e3SPaul Richards 222b9ae52e3SPaul Richards if (shp) 223b9ae52e3SPaul Richards /* Name exists: older version or just updated */ 224b9ae52e3SPaul Richards return; 225b9ae52e3SPaul Richards 226b9ae52e3SPaul Richards /* Allocate new list element */ 227b9ae52e3SPaul Richards if (verbose) 228b9ae52e3SPaul Richards printf("Adding %s/%s\n", dir, file); 229b9ae52e3SPaul Richards 230b9ae52e3SPaul Richards shp = (struct shlib_list *)xmalloc(sizeof *shp); 231b9ae52e3SPaul Richards shp->name = strdup(name); 232b9ae52e3SPaul Richards shp->path = concat(dir, "/", file); 233b9ae52e3SPaul Richards bcopy(dewey, shp->dewey, MAXDEWEY); 234b9ae52e3SPaul Richards shp->ndewey = ndewey; 235b9ae52e3SPaul Richards shp->next = NULL; 236b9ae52e3SPaul Richards 237b9ae52e3SPaul Richards *shlib_tail = shp; 238b9ae52e3SPaul Richards shlib_tail = &shp->next; 239b9ae52e3SPaul Richards } 240b9ae52e3SPaul Richards 241b9ae52e3SPaul Richards 242b9ae52e3SPaul Richards #if DEBUG 243b9ae52e3SPaul Richards /* test */ 244b9ae52e3SPaul Richards #undef _PATH_LD_HINTS 245b9ae52e3SPaul Richards #define _PATH_LD_HINTS "./ld.so.hints" 246b9ae52e3SPaul Richards #endif 247b9ae52e3SPaul Richards 248b9ae52e3SPaul Richards int 249d5453ba5SJoerg Wunsch hinthash(cp, vmajor) 250b9ae52e3SPaul Richards char *cp; 251d5453ba5SJoerg Wunsch int vmajor; 252b9ae52e3SPaul Richards { 253b9ae52e3SPaul Richards int k = 0; 254b9ae52e3SPaul Richards 255b9ae52e3SPaul Richards while (*cp) 256b9ae52e3SPaul Richards k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff; 257b9ae52e3SPaul Richards 258b9ae52e3SPaul Richards k = (((k << 1) + (k >> 14)) ^ (vmajor*257)) & 0x3fff; 259b9ae52e3SPaul Richards 260b9ae52e3SPaul Richards return k; 261b9ae52e3SPaul Richards } 262b9ae52e3SPaul Richards 263b9ae52e3SPaul Richards int 264f606c848SSatoshi Asami buildhints() 265b9ae52e3SPaul Richards { 266b9ae52e3SPaul Richards struct hints_header hdr; 267b9ae52e3SPaul Richards struct hints_bucket *blist; 268b9ae52e3SPaul Richards struct shlib_list *shp; 269b9ae52e3SPaul Richards char *strtab; 270b9ae52e3SPaul Richards int i, n, str_index = 0; 271b9ae52e3SPaul Richards int strtab_sz = 0; /* Total length of strings */ 272b9ae52e3SPaul Richards int nhints = 0; /* Total number of hints */ 273b9ae52e3SPaul Richards int fd; 274b9ae52e3SPaul Richards char *tmpfile; 275b9ae52e3SPaul Richards 276b9ae52e3SPaul Richards for (shp = shlib_head; shp; shp = shp->next) { 277b9ae52e3SPaul Richards strtab_sz += 1 + strlen(shp->name); 278b9ae52e3SPaul Richards strtab_sz += 1 + strlen(shp->path); 279b9ae52e3SPaul Richards nhints++; 280b9ae52e3SPaul Richards } 281b9ae52e3SPaul Richards 282b9ae52e3SPaul Richards /* Fill hints file header */ 283b9ae52e3SPaul Richards hdr.hh_magic = HH_MAGIC; 284b9ae52e3SPaul Richards hdr.hh_version = LD_HINTS_VERSION_1; 285b9ae52e3SPaul Richards hdr.hh_nbucket = 1 * nhints; 286b9ae52e3SPaul Richards n = hdr.hh_nbucket * sizeof(struct hints_bucket); 287b9ae52e3SPaul Richards hdr.hh_hashtab = sizeof(struct hints_header); 288b9ae52e3SPaul Richards hdr.hh_strtab = hdr.hh_hashtab + n; 289b9ae52e3SPaul Richards hdr.hh_strtab_sz = strtab_sz; 290b9ae52e3SPaul Richards hdr.hh_ehints = hdr.hh_strtab + hdr.hh_strtab_sz; 291b9ae52e3SPaul Richards 292b9ae52e3SPaul Richards if (verbose) 293526195adSJordan K. Hubbard printf("Totals: entries %d, buckets %ld, string size %d\n", 294b9ae52e3SPaul Richards nhints, hdr.hh_nbucket, strtab_sz); 295b9ae52e3SPaul Richards 296b9ae52e3SPaul Richards /* Allocate buckets and string table */ 297b9ae52e3SPaul Richards blist = (struct hints_bucket *)xmalloc(n); 298b9ae52e3SPaul Richards bzero((char *)blist, n); 299b9ae52e3SPaul Richards for (i = 0; i < hdr.hh_nbucket; i++) 300b9ae52e3SPaul Richards /* Empty all buckets */ 301b9ae52e3SPaul Richards blist[i].hi_next = -1; 302b9ae52e3SPaul Richards 303b9ae52e3SPaul Richards strtab = (char *)xmalloc(strtab_sz); 304b9ae52e3SPaul Richards 305b9ae52e3SPaul Richards /* Enter all */ 306b9ae52e3SPaul Richards for (shp = shlib_head; shp; shp = shp->next) { 307b9ae52e3SPaul Richards struct hints_bucket *bp; 308b9ae52e3SPaul Richards 309b9ae52e3SPaul Richards bp = blist + 310d5453ba5SJoerg Wunsch (hinthash(shp->name, shp->major) % hdr.hh_nbucket); 311b9ae52e3SPaul Richards 312b9ae52e3SPaul Richards if (bp->hi_pathx) { 313b9ae52e3SPaul Richards int i; 314b9ae52e3SPaul Richards 315b9ae52e3SPaul Richards for (i = 0; i < hdr.hh_nbucket; i++) { 316b9ae52e3SPaul Richards if (blist[i].hi_pathx == 0) 317b9ae52e3SPaul Richards break; 318b9ae52e3SPaul Richards } 319b9ae52e3SPaul Richards if (i == hdr.hh_nbucket) { 320f606c848SSatoshi Asami warnx("Bummer!"); 321b9ae52e3SPaul Richards return -1; 322b9ae52e3SPaul Richards } 323b9ae52e3SPaul Richards while (bp->hi_next != -1) 324b9ae52e3SPaul Richards bp = &blist[bp->hi_next]; 325b9ae52e3SPaul Richards bp->hi_next = i; 326b9ae52e3SPaul Richards bp = blist + i; 327b9ae52e3SPaul Richards } 328b9ae52e3SPaul Richards 329b9ae52e3SPaul Richards /* Insert strings in string table */ 330b9ae52e3SPaul Richards bp->hi_namex = str_index; 331b9ae52e3SPaul Richards strcpy(strtab + str_index, shp->name); 332b9ae52e3SPaul Richards str_index += 1 + strlen(shp->name); 333b9ae52e3SPaul Richards 334b9ae52e3SPaul Richards bp->hi_pathx = str_index; 335b9ae52e3SPaul Richards strcpy(strtab + str_index, shp->path); 336b9ae52e3SPaul Richards str_index += 1 + strlen(shp->path); 337b9ae52e3SPaul Richards 338b9ae52e3SPaul Richards /* Copy versions */ 339b9ae52e3SPaul Richards bcopy(shp->dewey, bp->hi_dewey, sizeof(bp->hi_dewey)); 340b9ae52e3SPaul Richards bp->hi_ndewey = shp->ndewey; 341b9ae52e3SPaul Richards } 342b9ae52e3SPaul Richards 3431c7895acSJoerg Wunsch umask(022); /* ensure the file will be worl-readable */ 344b9ae52e3SPaul Richards tmpfile = concat(_PATH_LD_HINTS, "+", ""); 345b9ae52e3SPaul Richards if ((fd = open(tmpfile, O_RDWR|O_CREAT|O_TRUNC, 0444)) == -1) { 346f606c848SSatoshi Asami warn("%s", _PATH_LD_HINTS); 347b9ae52e3SPaul Richards return -1; 348b9ae52e3SPaul Richards } 349b9ae52e3SPaul Richards 35009e3d49dSJordan K. Hubbard if (write(fd, &hdr, sizeof(struct hints_header)) != 35109e3d49dSJordan K. Hubbard sizeof(struct hints_header)) { 352f606c848SSatoshi Asami warn("%s", _PATH_LD_HINTS); 35309e3d49dSJordan K. Hubbard return -1; 35409e3d49dSJordan K. Hubbard } 35509e3d49dSJordan K. Hubbard if (write(fd, blist, hdr.hh_nbucket * sizeof(struct hints_bucket)) != 35609e3d49dSJordan K. Hubbard hdr.hh_nbucket * sizeof(struct hints_bucket)) { 357f606c848SSatoshi Asami warn("%s", _PATH_LD_HINTS); 35809e3d49dSJordan K. Hubbard return -1; 35909e3d49dSJordan K. Hubbard } 36009e3d49dSJordan K. Hubbard if (write(fd, strtab, strtab_sz) != strtab_sz) { 361f606c848SSatoshi Asami warn("%s", _PATH_LD_HINTS); 36209e3d49dSJordan K. Hubbard return -1; 36309e3d49dSJordan K. Hubbard } 364b9ae52e3SPaul Richards if (close(fd) != 0) { 365f606c848SSatoshi Asami warn("%s", _PATH_LD_HINTS); 366b9ae52e3SPaul Richards return -1; 367b9ae52e3SPaul Richards } 368b9ae52e3SPaul Richards 36909e3d49dSJordan K. Hubbard /* Install it */ 370b9ae52e3SPaul Richards if (unlink(_PATH_LD_HINTS) != 0 && errno != ENOENT) { 371f606c848SSatoshi Asami warn("%s", _PATH_LD_HINTS); 372b9ae52e3SPaul Richards return -1; 373b9ae52e3SPaul Richards } 374b9ae52e3SPaul Richards 375b9ae52e3SPaul Richards if (rename(tmpfile, _PATH_LD_HINTS) != 0) { 376f606c848SSatoshi Asami warn("%s", _PATH_LD_HINTS); 377b9ae52e3SPaul Richards return -1; 378b9ae52e3SPaul Richards } 379b9ae52e3SPaul Richards 380b9ae52e3SPaul Richards return 0; 381b9ae52e3SPaul Richards } 382b9ae52e3SPaul Richards 383699e1b82SRich Murphey static int 384f606c848SSatoshi Asami readhints() 385b9ae52e3SPaul Richards { 386b9ae52e3SPaul Richards int fd; 387b9ae52e3SPaul Richards caddr_t addr; 388b9ae52e3SPaul Richards long msize; 389b9ae52e3SPaul Richards struct hints_header *hdr; 390b9ae52e3SPaul Richards struct hints_bucket *blist; 391b9ae52e3SPaul Richards char *strtab; 392f606c848SSatoshi Asami struct shlib_list *shp; 393b9ae52e3SPaul Richards int i; 394b9ae52e3SPaul Richards 395b9ae52e3SPaul Richards if ((fd = open(_PATH_LD_HINTS, O_RDONLY, 0)) == -1) { 396f606c848SSatoshi Asami warn("%s", _PATH_LD_HINTS); 397b9ae52e3SPaul Richards return -1; 398b9ae52e3SPaul Richards } 399b9ae52e3SPaul Richards 400b9ae52e3SPaul Richards msize = PAGSIZ; 40161f9ce8dSNate Williams addr = mmap(0, msize, PROT_READ, MAP_COPY, fd, 0); 402b9ae52e3SPaul Richards 403b9ae52e3SPaul Richards if (addr == (caddr_t)-1) { 404f606c848SSatoshi Asami warn("%s", _PATH_LD_HINTS); 405b9ae52e3SPaul Richards return -1; 406b9ae52e3SPaul Richards } 407b9ae52e3SPaul Richards 408b9ae52e3SPaul Richards hdr = (struct hints_header *)addr; 409b9ae52e3SPaul Richards if (HH_BADMAG(*hdr)) { 410f606c848SSatoshi Asami warnx("%s: Bad magic: %o", 411699e1b82SRich Murphey _PATH_LD_HINTS, hdr->hh_magic); 412b9ae52e3SPaul Richards return -1; 413b9ae52e3SPaul Richards } 414b9ae52e3SPaul Richards 415b9ae52e3SPaul Richards if (hdr->hh_version != LD_HINTS_VERSION_1) { 416f606c848SSatoshi Asami warnx("Unsupported version: %d", hdr->hh_version); 417b9ae52e3SPaul Richards return -1; 418b9ae52e3SPaul Richards } 419b9ae52e3SPaul Richards 420b9ae52e3SPaul Richards if (hdr->hh_ehints > msize) { 421b9ae52e3SPaul Richards if (mmap(addr+msize, hdr->hh_ehints - msize, 42261f9ce8dSNate Williams PROT_READ, MAP_COPY|MAP_FIXED, 423b9ae52e3SPaul Richards fd, msize) != (caddr_t)(addr+msize)) { 424b9ae52e3SPaul Richards 425f606c848SSatoshi Asami warn("%s", _PATH_LD_HINTS); 426b9ae52e3SPaul Richards return -1; 427b9ae52e3SPaul Richards } 428b9ae52e3SPaul Richards } 429b9ae52e3SPaul Richards close(fd); 430b9ae52e3SPaul Richards 431b9ae52e3SPaul Richards blist = (struct hints_bucket *)(addr + hdr->hh_hashtab); 432b9ae52e3SPaul Richards strtab = (char *)(addr + hdr->hh_strtab); 433b9ae52e3SPaul Richards 434b9ae52e3SPaul Richards for (i = 0; i < hdr->hh_nbucket; i++) { 435b9ae52e3SPaul Richards struct hints_bucket *bp = &blist[i]; 436b9ae52e3SPaul Richards 437b9ae52e3SPaul Richards /* Sanity check */ 438b9ae52e3SPaul Richards if (bp->hi_namex >= hdr->hh_strtab_sz) { 439f606c848SSatoshi Asami warnx("Bad name index: %#x", bp->hi_namex); 440b9ae52e3SPaul Richards return -1; 441b9ae52e3SPaul Richards } 442b9ae52e3SPaul Richards if (bp->hi_pathx >= hdr->hh_strtab_sz) { 443f606c848SSatoshi Asami warnx("Bad path index: %#x", bp->hi_pathx); 444b9ae52e3SPaul Richards return -1; 445b9ae52e3SPaul Richards } 446b9ae52e3SPaul Richards 447f606c848SSatoshi Asami /* Allocate new list element */ 448f606c848SSatoshi Asami shp = (struct shlib_list *)xmalloc(sizeof *shp); 449f606c848SSatoshi Asami shp->name = strdup(strtab + bp->hi_namex); 450f606c848SSatoshi Asami shp->path = strdup(strtab + bp->hi_pathx); 451f606c848SSatoshi Asami bcopy(bp->hi_dewey, shp->dewey, sizeof(shp->dewey)); 452f606c848SSatoshi Asami shp->ndewey = bp->hi_ndewey; 453f606c848SSatoshi Asami shp->next = NULL; 454f606c848SSatoshi Asami 455f606c848SSatoshi Asami *shlib_tail = shp; 456f606c848SSatoshi Asami shlib_tail = &shp->next; 457b9ae52e3SPaul Richards } 458b9ae52e3SPaul Richards 459b9ae52e3SPaul Richards return 0; 460b9ae52e3SPaul Richards } 461b9ae52e3SPaul Richards 462f606c848SSatoshi Asami static void 463f606c848SSatoshi Asami listhints() 464f606c848SSatoshi Asami { 465f606c848SSatoshi Asami struct shlib_list *shp; 466f606c848SSatoshi Asami int i; 467f606c848SSatoshi Asami 468f606c848SSatoshi Asami printf("%s:\n", _PATH_LD_HINTS); 469f606c848SSatoshi Asami 470f606c848SSatoshi Asami for (i = 0, shp = shlib_head; shp; i++, shp = shp->next) 471f606c848SSatoshi Asami printf("\t%d:-l%s.%d.%d => %s\n", 472f606c848SSatoshi Asami i, shp->name, shp->major, shp->minor, shp->path); 473f606c848SSatoshi Asami 474f606c848SSatoshi Asami return; 475f606c848SSatoshi Asami } 476