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 */ 30b9ae52e3SPaul Richards 31b50d7faeSPhilippe Charnier #ifndef lint 32b50d7faeSPhilippe Charnier static const char rcsid[] = 337f3dea24SPeter Wemm "$FreeBSD$"; 34b50d7faeSPhilippe Charnier #endif /* not lint */ 35b50d7faeSPhilippe Charnier 36b9ae52e3SPaul Richards #include <sys/param.h> 37b9ae52e3SPaul Richards #include <sys/types.h> 38b9ae52e3SPaul Richards #include <sys/stat.h> 39b9ae52e3SPaul Richards #include <sys/mman.h> 40b9ae52e3SPaul Richards #include <a.out.h> 41b50d7faeSPhilippe Charnier #include <ctype.h> 42b50d7faeSPhilippe Charnier #include <dirent.h> 43a565ca59SJohn Polstra #include <elf.h> 44b50d7faeSPhilippe Charnier #include <err.h> 45b50d7faeSPhilippe Charnier #include <errno.h> 46b50d7faeSPhilippe Charnier #include <fcntl.h> 47b50d7faeSPhilippe Charnier #include <link.h> 48cfa4d739SJohn Polstra #include <objformat.h> 49699e1b82SRich Murphey #include <stdio.h> 50699e1b82SRich Murphey #include <stdlib.h> 51b9ae52e3SPaul Richards #include <string.h> 52699e1b82SRich Murphey #include <unistd.h> 53b9ae52e3SPaul Richards 54a565ca59SJohn Polstra #include "ldconfig.h" 5580c71499SPeter Wemm #include "shlib.h" 5680c71499SPeter Wemm #include "support.h" 5780c71499SPeter Wemm 587c6da7dcSJohn Polstra #if DEBUG 597c6da7dcSJohn Polstra /* test */ 607c6da7dcSJohn Polstra #undef _PATH_LD_HINTS 617c6da7dcSJohn Polstra #define _PATH_LD_HINTS "./ld.so.hints" 62a565ca59SJohn Polstra #undef _PATH_ELF_HINTS 63a565ca59SJohn Polstra #define _PATH_ELF_HINTS "./ld-elf.so.hints" 647c6da7dcSJohn Polstra #endif 65b9ae52e3SPaul Richards 66b9ae52e3SPaul Richards #undef major 67b9ae52e3SPaul Richards #undef minor 68b9ae52e3SPaul Richards 69b9ae52e3SPaul Richards static int verbose; 70b9ae52e3SPaul Richards static int nostd; 71b9ae52e3SPaul Richards static int justread; 72f606c848SSatoshi Asami static int merge; 73d4ba5766SPeter Wemm static int rescan; 74a565ca59SJohn Polstra static char *hints_file; 75b9ae52e3SPaul Richards 76b9ae52e3SPaul Richards struct shlib_list { 77b9ae52e3SPaul Richards /* Internal list of shared libraries found */ 78b9ae52e3SPaul Richards char *name; 79b9ae52e3SPaul Richards char *path; 80b9ae52e3SPaul Richards int dewey[MAXDEWEY]; 81b9ae52e3SPaul Richards int ndewey; 82b9ae52e3SPaul Richards #define major dewey[0] 83b9ae52e3SPaul Richards #define minor dewey[1] 84b9ae52e3SPaul Richards struct shlib_list *next; 85b9ae52e3SPaul Richards }; 86b9ae52e3SPaul Richards 87b9ae52e3SPaul Richards static struct shlib_list *shlib_head = NULL, **shlib_tail = &shlib_head; 8880c71499SPeter Wemm static char *dir_list; 89b9ae52e3SPaul Richards 90a565ca59SJohn Polstra static int buildhints __P((void)); 9109e3d49dSJordan K. Hubbard static int dodir __P((char *, int)); 92b50d7faeSPhilippe Charnier int dofile __P((char *, int)); 93a565ca59SJohn Polstra static void enter __P((char *, char *, char *, int *, int)); 94f606c848SSatoshi Asami static void listhints __P((void)); 95a565ca59SJohn Polstra static int readhints __P((void)); 96b50d7faeSPhilippe Charnier static void usage __P((void)); 97b9ae52e3SPaul Richards 98b9ae52e3SPaul Richards int 99b9ae52e3SPaul Richards main(argc, argv) 100b9ae52e3SPaul Richards int argc; 101b9ae52e3SPaul Richards char *argv[]; 102b9ae52e3SPaul Richards { 103b9ae52e3SPaul Richards int i, c; 104b9ae52e3SPaul Richards int rval = 0; 105cfa4d739SJohn Polstra char objformat[32]; 106cfa4d739SJohn Polstra int is_aout; 107b9ae52e3SPaul Richards 108cfa4d739SJohn Polstra if (getobjformat(objformat, sizeof objformat, &argc, argv) == -1) 109cfa4d739SJohn Polstra errx(1, "getobjformat failed: name too long"); 110cfa4d739SJohn Polstra if (strcmp(objformat, "aout") == 0) 111cfa4d739SJohn Polstra is_aout = 1; 112cfa4d739SJohn Polstra else if (strcmp(objformat, "elf") == 0) 113cfa4d739SJohn Polstra is_aout = 0; 114cfa4d739SJohn Polstra else 115cfa4d739SJohn Polstra errx(1, "unknown object format \"%s\"", objformat); 116cfa4d739SJohn Polstra 117cfa4d739SJohn Polstra hints_file = is_aout ? _PATH_LD_HINTS : _PATH_ELF_HINTS; 11897333b9eSJohn Polstra if (argc == 1) 11997333b9eSJohn Polstra rescan = 1; 120643dcf40SJohn Polstra else while((c = getopt(argc, argv, "Rf:imrsv")) != -1) { 121b9ae52e3SPaul Richards switch (c) { 122d4ba5766SPeter Wemm case 'R': 123d4ba5766SPeter Wemm rescan = 1; 124d4ba5766SPeter Wemm break; 1257c6da7dcSJohn Polstra case 'f': 1267c6da7dcSJohn Polstra hints_file = optarg; 1277c6da7dcSJohn Polstra break; 128643dcf40SJohn Polstra case 'i': 129643dcf40SJohn Polstra insecure = 1; 130643dcf40SJohn Polstra break; 131f606c848SSatoshi Asami case 'm': 132f606c848SSatoshi Asami merge = 1; 133b9ae52e3SPaul Richards break; 134b9ae52e3SPaul Richards case 'r': 135b9ae52e3SPaul Richards justread = 1; 136b9ae52e3SPaul Richards break; 137f606c848SSatoshi Asami case 's': 138f606c848SSatoshi Asami nostd = 1; 139f606c848SSatoshi Asami break; 140f606c848SSatoshi Asami case 'v': 141f606c848SSatoshi Asami verbose = 1; 142f606c848SSatoshi Asami break; 143b9ae52e3SPaul Richards default: 144b50d7faeSPhilippe Charnier usage(); 145b9ae52e3SPaul Richards break; 146b9ae52e3SPaul Richards } 147b9ae52e3SPaul Richards } 148b9ae52e3SPaul Richards 149cfa4d739SJohn Polstra if (!is_aout) { 150a565ca59SJohn Polstra if (justread) 151a565ca59SJohn Polstra list_elf_hints(hints_file); 152a565ca59SJohn Polstra else 153a565ca59SJohn Polstra update_elf_hints(hints_file, argc - optind, 154a565ca59SJohn Polstra argv + optind, merge || rescan); 155a565ca59SJohn Polstra return 0; 156a565ca59SJohn Polstra } 157a565ca59SJohn Polstra 158643dcf40SJohn Polstra /* Here begins the aout libs processing */ 15980c71499SPeter Wemm dir_list = strdup(""); 16080c71499SPeter Wemm 161d4ba5766SPeter Wemm if (justread || merge || rescan) { 162f606c848SSatoshi Asami if ((rval = readhints()) != 0) 163f606c848SSatoshi Asami return rval; 16480c71499SPeter Wemm } 16580c71499SPeter Wemm 166d4ba5766SPeter Wemm if (!nostd && !merge && !rescan) 16780c71499SPeter Wemm std_search_path(); 16880c71499SPeter Wemm 169571b472bSJordan K. Hubbard /* Add any directories/files from the command line */ 170571b472bSJordan K. Hubbard if (!justread) { 171d66f9d22SJohn Polstra for (i = optind; i < argc; i++) { 172571b472bSJordan K. Hubbard struct stat stbuf; 173571b472bSJordan K. Hubbard 174571b472bSJordan K. Hubbard if (stat(argv[i], &stbuf) == -1) { 175d66f9d22SJohn Polstra warn("%s", argv[i]); 176d66f9d22SJohn Polstra rval = -1; 177614d19caSJohn Polstra } else if (strcmp(argv[i], "/usr/lib") == 0) { 178cabb97dcSSøren Schmidt warnx("WARNING! '%s' can not be used", argv[i]); 179cabb97dcSSøren Schmidt rval = -1; 180614d19caSJohn Polstra } else { 181571b472bSJordan K. Hubbard /* 182571b472bSJordan K. Hubbard * See if this is a directory-containing 183571b472bSJordan K. Hubbard * file instead of a directory 184571b472bSJordan K. Hubbard */ 185571b472bSJordan K. Hubbard if (S_ISREG(stbuf.st_mode)) 186571b472bSJordan K. Hubbard rval |= dofile(argv[i], 0); 187571b472bSJordan K. Hubbard else 18880c71499SPeter Wemm add_search_path(argv[i]); 189d66f9d22SJohn Polstra } 190d66f9d22SJohn Polstra } 191571b472bSJordan K. Hubbard } 19280c71499SPeter Wemm 19380c71499SPeter Wemm for (i = 0; i < n_search_dirs; i++) { 19480c71499SPeter Wemm char *cp = concat(dir_list, *dir_list?":":"", search_dirs[i]); 19580c71499SPeter Wemm free(dir_list); 19680c71499SPeter Wemm dir_list = cp; 19780c71499SPeter Wemm } 19880c71499SPeter Wemm 199f606c848SSatoshi Asami if (justread) { 200f606c848SSatoshi Asami listhints(); 201526195adSJordan K. Hubbard return 0; 202f606c848SSatoshi Asami } 203b9ae52e3SPaul Richards 204b9ae52e3SPaul Richards for (i = 0; i < n_search_dirs; i++) 20509e3d49dSJordan K. Hubbard rval |= dodir(search_dirs[i], 1); 206b9ae52e3SPaul Richards 207f606c848SSatoshi Asami rval |= buildhints(); 208b9ae52e3SPaul Richards 209b9ae52e3SPaul Richards return rval; 210b9ae52e3SPaul Richards } 211b9ae52e3SPaul Richards 212b50d7faeSPhilippe Charnier static void 213b50d7faeSPhilippe Charnier usage() 214b50d7faeSPhilippe Charnier { 215b50d7faeSPhilippe Charnier fprintf(stderr, 216643dcf40SJohn Polstra "usage: ldconfig [-aout | -elf] [-Rimrsv] [-f hints_file] [dir | file ...]\n"); 217b50d7faeSPhilippe Charnier exit(1); 218b50d7faeSPhilippe Charnier } 219b50d7faeSPhilippe Charnier 220b9ae52e3SPaul Richards int 221571b472bSJordan K. Hubbard dofile(fname, silent) 222571b472bSJordan K. Hubbard char *fname; 223571b472bSJordan K. Hubbard int silent; 224571b472bSJordan K. Hubbard { 225571b472bSJordan K. Hubbard FILE *hfp; 226571b472bSJordan K. Hubbard char buf[MAXPATHLEN]; 227571b472bSJordan K. Hubbard int rval = 0; 228571b472bSJordan K. Hubbard char *cp, *sp; 229571b472bSJordan K. Hubbard 230571b472bSJordan K. Hubbard if ((hfp = fopen(fname, "r")) == NULL) { 231571b472bSJordan K. Hubbard warn("%s", fname); 232571b472bSJordan K. Hubbard return -1; 233571b472bSJordan K. Hubbard } 234571b472bSJordan K. Hubbard 235571b472bSJordan K. Hubbard while (fgets(buf, sizeof(buf), hfp)) { 236571b472bSJordan K. Hubbard cp = buf; 237571b472bSJordan K. Hubbard while (isspace(*cp)) 238571b472bSJordan K. Hubbard cp++; 239571b472bSJordan K. Hubbard if (*cp == '#' || *cp == '\0') 240571b472bSJordan K. Hubbard continue; 241571b472bSJordan K. Hubbard sp = cp; 242571b472bSJordan K. Hubbard while (!isspace(*cp) && *cp != '\0') 243571b472bSJordan K. Hubbard cp++; 244571b472bSJordan K. Hubbard 245571b472bSJordan K. Hubbard if (*cp != '\n') { 246571b472bSJordan K. Hubbard *cp = '\0'; 247b50d7faeSPhilippe Charnier warnx("%s: trailing characters ignored", sp); 248571b472bSJordan K. Hubbard } 249571b472bSJordan K. Hubbard 250571b472bSJordan K. Hubbard *cp = '\0'; 251571b472bSJordan K. Hubbard 252571b472bSJordan K. Hubbard rval |= dodir(sp, silent); 253571b472bSJordan K. Hubbard } 254571b472bSJordan K. Hubbard 255571b472bSJordan K. Hubbard (void)fclose(hfp); 256571b472bSJordan K. Hubbard return rval; 257571b472bSJordan K. Hubbard } 258571b472bSJordan K. Hubbard 259571b472bSJordan K. Hubbard int 26009e3d49dSJordan K. Hubbard dodir(dir, silent) 261b9ae52e3SPaul Richards char *dir; 26209e3d49dSJordan K. Hubbard int silent; 263b9ae52e3SPaul Richards { 264b9ae52e3SPaul Richards DIR *dd; 265b9ae52e3SPaul Richards struct dirent *dp; 2660f6b2cb3SPaul Traina char name[MAXPATHLEN]; 267b9ae52e3SPaul Richards int dewey[MAXDEWEY], ndewey; 268b9ae52e3SPaul Richards 269b9ae52e3SPaul Richards if ((dd = opendir(dir)) == NULL) { 270d66f9d22SJohn Polstra if (silent && errno == ENOENT) /* Ignore the error */ 271d66f9d22SJohn Polstra return 0; 272f606c848SSatoshi Asami warn("%s", dir); 273b9ae52e3SPaul Richards return -1; 274b9ae52e3SPaul Richards } 275b9ae52e3SPaul Richards 276b9ae52e3SPaul Richards while ((dp = readdir(dd)) != NULL) { 2770f6b2cb3SPaul Traina register int n; 2780f6b2cb3SPaul Traina register char *cp; 279b9ae52e3SPaul Richards 2800f6b2cb3SPaul Traina /* Check for `lib' prefix */ 2810f6b2cb3SPaul Traina if (dp->d_name[0] != 'l' || 2820f6b2cb3SPaul Traina dp->d_name[1] != 'i' || 2830f6b2cb3SPaul Traina dp->d_name[2] != 'b') 284b9ae52e3SPaul Richards continue; 285b9ae52e3SPaul Richards 2860f6b2cb3SPaul Traina /* Copy the entry minus prefix */ 2870f6b2cb3SPaul Traina (void)strcpy(name, dp->d_name + 3); 2880f6b2cb3SPaul Traina n = strlen(name); 2890f6b2cb3SPaul Traina if (n < 4) 2900f6b2cb3SPaul Traina continue; 2910f6b2cb3SPaul Traina 2920f6b2cb3SPaul Traina /* Find ".so." in name */ 2930f6b2cb3SPaul Traina for (cp = name + n - 4; cp > name; --cp) { 2940f6b2cb3SPaul Traina if (cp[0] == '.' && 2950f6b2cb3SPaul Traina cp[1] == 's' && 2960f6b2cb3SPaul Traina cp[2] == 'o' && 2970f6b2cb3SPaul Traina cp[3] == '.') 2980f6b2cb3SPaul Traina break; 2990f6b2cb3SPaul Traina } 3000f6b2cb3SPaul Traina if (cp <= name) 3010f6b2cb3SPaul Traina continue; 3020f6b2cb3SPaul Traina 3030f6b2cb3SPaul Traina *cp = '\0'; 3040f6b2cb3SPaul Traina if (!isdigit(*(cp+4))) 3050f6b2cb3SPaul Traina continue; 3060f6b2cb3SPaul Traina 3070f6b2cb3SPaul Traina bzero((caddr_t)dewey, sizeof(dewey)); 3080f6b2cb3SPaul Traina ndewey = getdewey(dewey, cp + 4); 3095f8d88ddSJohn Polstra if (ndewey < 2) 3105f8d88ddSJohn Polstra continue; 311b9ae52e3SPaul Richards enter(dir, dp->d_name, name, dewey, ndewey); 312b9ae52e3SPaul Richards } 313b9ae52e3SPaul Richards 314571b472bSJordan K. Hubbard closedir(dd); 315b9ae52e3SPaul Richards return 0; 316b9ae52e3SPaul Richards } 317b9ae52e3SPaul Richards 318b9ae52e3SPaul Richards static void 319b9ae52e3SPaul Richards enter(dir, file, name, dewey, ndewey) 320b9ae52e3SPaul Richards char *dir, *file, *name; 321b9ae52e3SPaul Richards int dewey[], ndewey; 322b9ae52e3SPaul Richards { 323b9ae52e3SPaul Richards struct shlib_list *shp; 324b9ae52e3SPaul Richards 325b9ae52e3SPaul Richards for (shp = shlib_head; shp; shp = shp->next) { 326b9ae52e3SPaul Richards if (strcmp(name, shp->name) != 0 || major != shp->major) 327b9ae52e3SPaul Richards continue; 328b9ae52e3SPaul Richards 329b9ae52e3SPaul Richards /* Name matches existing entry */ 330b9ae52e3SPaul Richards if (cmpndewey(dewey, ndewey, shp->dewey, shp->ndewey) > 0) { 331b9ae52e3SPaul Richards 332b9ae52e3SPaul Richards /* Update this entry with higher versioned lib */ 333b9ae52e3SPaul Richards if (verbose) 334b9ae52e3SPaul Richards printf("Updating lib%s.%d.%d to %s/%s\n", 335b9ae52e3SPaul Richards shp->name, shp->major, shp->minor, 336b9ae52e3SPaul Richards dir, file); 337b9ae52e3SPaul Richards 338b9ae52e3SPaul Richards free(shp->name); 339b9ae52e3SPaul Richards shp->name = strdup(name); 340b9ae52e3SPaul Richards free(shp->path); 341b9ae52e3SPaul Richards shp->path = concat(dir, "/", file); 342b9ae52e3SPaul Richards bcopy(dewey, shp->dewey, sizeof(shp->dewey)); 343b9ae52e3SPaul Richards shp->ndewey = ndewey; 344b9ae52e3SPaul Richards } 345b9ae52e3SPaul Richards break; 346b9ae52e3SPaul Richards } 347b9ae52e3SPaul Richards 348b9ae52e3SPaul Richards if (shp) 349b9ae52e3SPaul Richards /* Name exists: older version or just updated */ 350b9ae52e3SPaul Richards return; 351b9ae52e3SPaul Richards 352b9ae52e3SPaul Richards /* Allocate new list element */ 353b9ae52e3SPaul Richards if (verbose) 354b9ae52e3SPaul Richards printf("Adding %s/%s\n", dir, file); 355b9ae52e3SPaul Richards 356b9ae52e3SPaul Richards shp = (struct shlib_list *)xmalloc(sizeof *shp); 357b9ae52e3SPaul Richards shp->name = strdup(name); 358b9ae52e3SPaul Richards shp->path = concat(dir, "/", file); 359b9ae52e3SPaul Richards bcopy(dewey, shp->dewey, MAXDEWEY); 360b9ae52e3SPaul Richards shp->ndewey = ndewey; 361b9ae52e3SPaul Richards shp->next = NULL; 362b9ae52e3SPaul Richards 363b9ae52e3SPaul Richards *shlib_tail = shp; 364b9ae52e3SPaul Richards shlib_tail = &shp->next; 365b9ae52e3SPaul Richards } 366b9ae52e3SPaul Richards 367b9ae52e3SPaul Richards 368b9ae52e3SPaul Richards int 369d5453ba5SJoerg Wunsch hinthash(cp, vmajor) 370b9ae52e3SPaul Richards char *cp; 371d5453ba5SJoerg Wunsch int vmajor; 372b9ae52e3SPaul Richards { 373b9ae52e3SPaul Richards int k = 0; 374b9ae52e3SPaul Richards 375b9ae52e3SPaul Richards while (*cp) 376b9ae52e3SPaul Richards k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff; 377b9ae52e3SPaul Richards 378b9ae52e3SPaul Richards k = (((k << 1) + (k >> 14)) ^ (vmajor*257)) & 0x3fff; 379b9ae52e3SPaul Richards 380b9ae52e3SPaul Richards return k; 381b9ae52e3SPaul Richards } 382b9ae52e3SPaul Richards 383b9ae52e3SPaul Richards int 384f606c848SSatoshi Asami buildhints() 385b9ae52e3SPaul Richards { 386b9ae52e3SPaul Richards struct hints_header hdr; 387b9ae52e3SPaul Richards struct hints_bucket *blist; 388b9ae52e3SPaul Richards struct shlib_list *shp; 389b9ae52e3SPaul Richards char *strtab; 390b9ae52e3SPaul Richards int i, n, str_index = 0; 391b9ae52e3SPaul Richards int strtab_sz = 0; /* Total length of strings */ 392b9ae52e3SPaul Richards int nhints = 0; /* Total number of hints */ 393b9ae52e3SPaul Richards int fd; 394b9ae52e3SPaul Richards char *tmpfile; 395b9ae52e3SPaul Richards 396b9ae52e3SPaul Richards for (shp = shlib_head; shp; shp = shp->next) { 397b9ae52e3SPaul Richards strtab_sz += 1 + strlen(shp->name); 398b9ae52e3SPaul Richards strtab_sz += 1 + strlen(shp->path); 399b9ae52e3SPaul Richards nhints++; 400b9ae52e3SPaul Richards } 401b9ae52e3SPaul Richards 402b9ae52e3SPaul Richards /* Fill hints file header */ 403b9ae52e3SPaul Richards hdr.hh_magic = HH_MAGIC; 40480c71499SPeter Wemm hdr.hh_version = LD_HINTS_VERSION_2; 405b9ae52e3SPaul Richards hdr.hh_nbucket = 1 * nhints; 406b9ae52e3SPaul Richards n = hdr.hh_nbucket * sizeof(struct hints_bucket); 407b9ae52e3SPaul Richards hdr.hh_hashtab = sizeof(struct hints_header); 408b9ae52e3SPaul Richards hdr.hh_strtab = hdr.hh_hashtab + n; 40980c71499SPeter Wemm hdr.hh_dirlist = strtab_sz; 41080c71499SPeter Wemm strtab_sz += 1 + strlen(dir_list); 411b9ae52e3SPaul Richards hdr.hh_strtab_sz = strtab_sz; 412b9ae52e3SPaul Richards hdr.hh_ehints = hdr.hh_strtab + hdr.hh_strtab_sz; 413b9ae52e3SPaul Richards 414b9ae52e3SPaul Richards if (verbose) 415526195adSJordan K. Hubbard printf("Totals: entries %d, buckets %ld, string size %d\n", 416ab845347SBruce Evans nhints, (long)hdr.hh_nbucket, strtab_sz); 417b9ae52e3SPaul Richards 418b9ae52e3SPaul Richards /* Allocate buckets and string table */ 419b9ae52e3SPaul Richards blist = (struct hints_bucket *)xmalloc(n); 420b9ae52e3SPaul Richards bzero((char *)blist, n); 421b9ae52e3SPaul Richards for (i = 0; i < hdr.hh_nbucket; i++) 422b9ae52e3SPaul Richards /* Empty all buckets */ 423b9ae52e3SPaul Richards blist[i].hi_next = -1; 424b9ae52e3SPaul Richards 425b9ae52e3SPaul Richards strtab = (char *)xmalloc(strtab_sz); 426b9ae52e3SPaul Richards 427b9ae52e3SPaul Richards /* Enter all */ 428b9ae52e3SPaul Richards for (shp = shlib_head; shp; shp = shp->next) { 429b9ae52e3SPaul Richards struct hints_bucket *bp; 430b9ae52e3SPaul Richards 431b9ae52e3SPaul Richards bp = blist + 432d5453ba5SJoerg Wunsch (hinthash(shp->name, shp->major) % hdr.hh_nbucket); 433b9ae52e3SPaul Richards 434b9ae52e3SPaul Richards if (bp->hi_pathx) { 435b9ae52e3SPaul Richards int i; 436b9ae52e3SPaul Richards 437b9ae52e3SPaul Richards for (i = 0; i < hdr.hh_nbucket; i++) { 438b9ae52e3SPaul Richards if (blist[i].hi_pathx == 0) 439b9ae52e3SPaul Richards break; 440b9ae52e3SPaul Richards } 441b9ae52e3SPaul Richards if (i == hdr.hh_nbucket) { 442b50d7faeSPhilippe Charnier warnx("bummer!"); 443b9ae52e3SPaul Richards return -1; 444b9ae52e3SPaul Richards } 445b9ae52e3SPaul Richards while (bp->hi_next != -1) 446b9ae52e3SPaul Richards bp = &blist[bp->hi_next]; 447b9ae52e3SPaul Richards bp->hi_next = i; 448b9ae52e3SPaul Richards bp = blist + i; 449b9ae52e3SPaul Richards } 450b9ae52e3SPaul Richards 451b9ae52e3SPaul Richards /* Insert strings in string table */ 452b9ae52e3SPaul Richards bp->hi_namex = str_index; 453b9ae52e3SPaul Richards strcpy(strtab + str_index, shp->name); 454b9ae52e3SPaul Richards str_index += 1 + strlen(shp->name); 455b9ae52e3SPaul Richards 456b9ae52e3SPaul Richards bp->hi_pathx = str_index; 457b9ae52e3SPaul Richards strcpy(strtab + str_index, shp->path); 458b9ae52e3SPaul Richards str_index += 1 + strlen(shp->path); 459b9ae52e3SPaul Richards 460b9ae52e3SPaul Richards /* Copy versions */ 461b9ae52e3SPaul Richards bcopy(shp->dewey, bp->hi_dewey, sizeof(bp->hi_dewey)); 462b9ae52e3SPaul Richards bp->hi_ndewey = shp->ndewey; 463b9ae52e3SPaul Richards } 464b9ae52e3SPaul Richards 46580c71499SPeter Wemm /* Copy search directories */ 46680c71499SPeter Wemm strcpy(strtab + str_index, dir_list); 46780c71499SPeter Wemm str_index += 1 + strlen(dir_list); 46880c71499SPeter Wemm 46980c71499SPeter Wemm /* Sanity check */ 47080c71499SPeter Wemm if (str_index != strtab_sz) { 47180c71499SPeter Wemm errx(1, "str_index(%d) != strtab_sz(%d)", str_index, strtab_sz); 47280c71499SPeter Wemm } 47380c71499SPeter Wemm 47416bd17ceSKris Kennaway tmpfile = concat(hints_file, ".XXXXXXXXXX", ""); 47516bd17ceSKris Kennaway umask(0); /* Create with exact permissions */ 47616bd17ceSKris Kennaway if ((fd = mkstemp(tmpfile)) == -1) { 47780c71499SPeter Wemm warn("%s", tmpfile); 47880c71499SPeter Wemm return -1; 47980c71499SPeter Wemm } 48016bd17ceSKris Kennaway fchmod(fd, 0444); 481b9ae52e3SPaul Richards 48209e3d49dSJordan K. Hubbard if (write(fd, &hdr, sizeof(struct hints_header)) != 48309e3d49dSJordan K. Hubbard sizeof(struct hints_header)) { 4847c6da7dcSJohn Polstra warn("%s", hints_file); 48509e3d49dSJordan K. Hubbard return -1; 48609e3d49dSJordan K. Hubbard } 48709e3d49dSJordan K. Hubbard if (write(fd, blist, hdr.hh_nbucket * sizeof(struct hints_bucket)) != 48809e3d49dSJordan K. Hubbard hdr.hh_nbucket * sizeof(struct hints_bucket)) { 4897c6da7dcSJohn Polstra warn("%s", hints_file); 49009e3d49dSJordan K. Hubbard return -1; 49109e3d49dSJordan K. Hubbard } 49209e3d49dSJordan K. Hubbard if (write(fd, strtab, strtab_sz) != strtab_sz) { 4937c6da7dcSJohn Polstra warn("%s", hints_file); 49409e3d49dSJordan K. Hubbard return -1; 49509e3d49dSJordan K. Hubbard } 496b9ae52e3SPaul Richards if (close(fd) != 0) { 4977c6da7dcSJohn Polstra warn("%s", hints_file); 498b9ae52e3SPaul Richards return -1; 499b9ae52e3SPaul Richards } 500b9ae52e3SPaul Richards 50109e3d49dSJordan K. Hubbard /* Install it */ 5027c6da7dcSJohn Polstra if (unlink(hints_file) != 0 && errno != ENOENT) { 5037c6da7dcSJohn Polstra warn("%s", hints_file); 504b9ae52e3SPaul Richards return -1; 505b9ae52e3SPaul Richards } 506b9ae52e3SPaul Richards 5077c6da7dcSJohn Polstra if (rename(tmpfile, hints_file) != 0) { 5087c6da7dcSJohn Polstra warn("%s", hints_file); 509b9ae52e3SPaul Richards return -1; 510b9ae52e3SPaul Richards } 511b9ae52e3SPaul Richards 512b9ae52e3SPaul Richards return 0; 513b9ae52e3SPaul Richards } 514b9ae52e3SPaul Richards 515699e1b82SRich Murphey static int 516f606c848SSatoshi Asami readhints() 517b9ae52e3SPaul Richards { 518b9ae52e3SPaul Richards int fd; 519614d19caSJohn Polstra void *addr; 520614d19caSJohn Polstra long fsize; 521b9ae52e3SPaul Richards long msize; 522b9ae52e3SPaul Richards struct hints_header *hdr; 523b9ae52e3SPaul Richards struct hints_bucket *blist; 524b9ae52e3SPaul Richards char *strtab; 525f606c848SSatoshi Asami struct shlib_list *shp; 526b9ae52e3SPaul Richards int i; 527b9ae52e3SPaul Richards 5287c6da7dcSJohn Polstra if ((fd = open(hints_file, O_RDONLY, 0)) == -1) { 5297c6da7dcSJohn Polstra warn("%s", hints_file); 530b9ae52e3SPaul Richards return -1; 531b9ae52e3SPaul Richards } 532b9ae52e3SPaul Richards 53380c71499SPeter Wemm msize = PAGE_SIZE; 53461f9ce8dSNate Williams addr = mmap(0, msize, PROT_READ, MAP_COPY, fd, 0); 535b9ae52e3SPaul Richards 536614d19caSJohn Polstra if (addr == MAP_FAILED) { 5377c6da7dcSJohn Polstra warn("%s", hints_file); 538b9ae52e3SPaul Richards return -1; 539b9ae52e3SPaul Richards } 540b9ae52e3SPaul Richards 541b9ae52e3SPaul Richards hdr = (struct hints_header *)addr; 542b9ae52e3SPaul Richards if (HH_BADMAG(*hdr)) { 543ab845347SBruce Evans warnx("%s: bad magic: %lo", hints_file, 544ab845347SBruce Evans (unsigned long)hdr->hh_magic); 545b9ae52e3SPaul Richards return -1; 546b9ae52e3SPaul Richards } 547b9ae52e3SPaul Richards 54880c71499SPeter Wemm if (hdr->hh_version != LD_HINTS_VERSION_1 && 54980c71499SPeter Wemm hdr->hh_version != LD_HINTS_VERSION_2) { 550ab845347SBruce Evans warnx("unsupported version: %ld", (long)hdr->hh_version); 551b9ae52e3SPaul Richards return -1; 552b9ae52e3SPaul Richards } 553b9ae52e3SPaul Richards 554b9ae52e3SPaul Richards if (hdr->hh_ehints > msize) { 555614d19caSJohn Polstra fsize = hdr->hh_ehints; 556614d19caSJohn Polstra munmap(addr, msize); 557614d19caSJohn Polstra addr = mmap(0, fsize, PROT_READ, MAP_COPY, fd, 0); 558614d19caSJohn Polstra if (addr == MAP_FAILED) { 5597c6da7dcSJohn Polstra warn("%s", hints_file); 560b9ae52e3SPaul Richards return -1; 561b9ae52e3SPaul Richards } 562614d19caSJohn Polstra hdr = (struct hints_header *)addr; 563b9ae52e3SPaul Richards } 564b9ae52e3SPaul Richards close(fd); 565b9ae52e3SPaul Richards 566b9ae52e3SPaul Richards blist = (struct hints_bucket *)(addr + hdr->hh_hashtab); 567b9ae52e3SPaul Richards strtab = (char *)(addr + hdr->hh_strtab); 568b9ae52e3SPaul Richards 569d4ba5766SPeter Wemm if (hdr->hh_version >= LD_HINTS_VERSION_2) 570d4ba5766SPeter Wemm add_search_path(strtab + hdr->hh_dirlist); 571d4ba5766SPeter Wemm else if (rescan) 572d4ba5766SPeter Wemm errx(1, "%s too old and does not contain the search path", 573d4ba5766SPeter Wemm hints_file); 574d4ba5766SPeter Wemm 575d4ba5766SPeter Wemm if (rescan) 576d4ba5766SPeter Wemm return 0; 577d4ba5766SPeter Wemm 578b9ae52e3SPaul Richards for (i = 0; i < hdr->hh_nbucket; i++) { 579b9ae52e3SPaul Richards struct hints_bucket *bp = &blist[i]; 580b9ae52e3SPaul Richards 581b9ae52e3SPaul Richards /* Sanity check */ 582b9ae52e3SPaul Richards if (bp->hi_namex >= hdr->hh_strtab_sz) { 583b50d7faeSPhilippe Charnier warnx("bad name index: %#x", bp->hi_namex); 584b9ae52e3SPaul Richards return -1; 585b9ae52e3SPaul Richards } 586b9ae52e3SPaul Richards if (bp->hi_pathx >= hdr->hh_strtab_sz) { 587b50d7faeSPhilippe Charnier warnx("bad path index: %#x", bp->hi_pathx); 588b9ae52e3SPaul Richards return -1; 589b9ae52e3SPaul Richards } 590b9ae52e3SPaul Richards 591f606c848SSatoshi Asami /* Allocate new list element */ 592f606c848SSatoshi Asami shp = (struct shlib_list *)xmalloc(sizeof *shp); 593f606c848SSatoshi Asami shp->name = strdup(strtab + bp->hi_namex); 594f606c848SSatoshi Asami shp->path = strdup(strtab + bp->hi_pathx); 595f606c848SSatoshi Asami bcopy(bp->hi_dewey, shp->dewey, sizeof(shp->dewey)); 596f606c848SSatoshi Asami shp->ndewey = bp->hi_ndewey; 597f606c848SSatoshi Asami shp->next = NULL; 598f606c848SSatoshi Asami 599f606c848SSatoshi Asami *shlib_tail = shp; 600f606c848SSatoshi Asami shlib_tail = &shp->next; 601b9ae52e3SPaul Richards } 602b9ae52e3SPaul Richards 603b9ae52e3SPaul Richards return 0; 604b9ae52e3SPaul Richards } 605b9ae52e3SPaul Richards 606f606c848SSatoshi Asami static void 607f606c848SSatoshi Asami listhints() 608f606c848SSatoshi Asami { 609f606c848SSatoshi Asami struct shlib_list *shp; 610f606c848SSatoshi Asami int i; 611f606c848SSatoshi Asami 6127c6da7dcSJohn Polstra printf("%s:\n", hints_file); 61380c71499SPeter Wemm printf("\tsearch directories: %s\n", dir_list); 614f606c848SSatoshi Asami 615f606c848SSatoshi Asami for (i = 0, shp = shlib_head; shp; i++, shp = shp->next) 616f606c848SSatoshi Asami printf("\t%d:-l%s.%d.%d => %s\n", 617f606c848SSatoshi Asami i, shp->name, shp->major, shp->minor, shp->path); 618f606c848SSatoshi Asami 619f606c848SSatoshi Asami return; 620f606c848SSatoshi Asami } 621