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 * 30571b472bSJordan K. Hubbard * $Id: ldconfig.c,v 1.18 1997/02/22 15:46:38 peter 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 5480c71499SPeter Wemm #include <machine/param.h> 5580c71499SPeter Wemm 5680c71499SPeter Wemm #include <link.h> 5780c71499SPeter Wemm #include "shlib.h" 5880c71499SPeter Wemm #include "support.h" 5980c71499SPeter Wemm 607c6da7dcSJohn Polstra #if DEBUG 617c6da7dcSJohn Polstra /* test */ 627c6da7dcSJohn Polstra #undef _PATH_LD_HINTS 637c6da7dcSJohn Polstra #define _PATH_LD_HINTS "./ld.so.hints" 647c6da7dcSJohn Polstra #endif 65b9ae52e3SPaul Richards 66b9ae52e3SPaul Richards #undef major 67b9ae52e3SPaul Richards #undef minor 68b9ae52e3SPaul Richards 6961f9ce8dSNate Williams extern char *__progname; 7061f9ce8dSNate Williams 71b9ae52e3SPaul Richards static int verbose; 72b9ae52e3SPaul Richards static int nostd; 73b9ae52e3SPaul Richards static int justread; 74f606c848SSatoshi Asami static int merge; 757c6da7dcSJohn Polstra static char *hints_file = _PATH_LD_HINTS; 76b9ae52e3SPaul Richards 77b9ae52e3SPaul Richards struct shlib_list { 78b9ae52e3SPaul Richards /* Internal list of shared libraries found */ 79b9ae52e3SPaul Richards char *name; 80b9ae52e3SPaul Richards char *path; 81b9ae52e3SPaul Richards int dewey[MAXDEWEY]; 82b9ae52e3SPaul Richards int ndewey; 83b9ae52e3SPaul Richards #define major dewey[0] 84b9ae52e3SPaul Richards #define minor dewey[1] 85b9ae52e3SPaul Richards struct shlib_list *next; 86b9ae52e3SPaul Richards }; 87b9ae52e3SPaul Richards 88b9ae52e3SPaul Richards static struct shlib_list *shlib_head = NULL, **shlib_tail = &shlib_head; 8980c71499SPeter Wemm static char *dir_list; 90b9ae52e3SPaul Richards 91b9ae52e3SPaul Richards static void enter __P((char *, char *, char *, int *, int)); 9209e3d49dSJordan K. Hubbard static int dodir __P((char *, int)); 93f606c848SSatoshi Asami static int buildhints __P((void)); 94f606c848SSatoshi Asami static int readhints __P((void)); 95f606c848SSatoshi Asami static void listhints __P((void)); 96b9ae52e3SPaul Richards 97b9ae52e3SPaul Richards int 98b9ae52e3SPaul Richards main(argc, argv) 99b9ae52e3SPaul Richards int argc; 100b9ae52e3SPaul Richards char *argv[]; 101b9ae52e3SPaul Richards { 102b9ae52e3SPaul Richards int i, c; 103b9ae52e3SPaul Richards int rval = 0; 104b9ae52e3SPaul Richards 1057c6da7dcSJohn Polstra while ((c = getopt(argc, argv, "f:mrsv")) != EOF) { 106b9ae52e3SPaul Richards switch (c) { 1077c6da7dcSJohn Polstra case 'f': 1087c6da7dcSJohn Polstra hints_file = optarg; 1097c6da7dcSJohn Polstra break; 110f606c848SSatoshi Asami case 'm': 111f606c848SSatoshi Asami merge = 1; 112b9ae52e3SPaul Richards break; 113b9ae52e3SPaul Richards case 'r': 114b9ae52e3SPaul Richards justread = 1; 115b9ae52e3SPaul Richards break; 116f606c848SSatoshi Asami case 's': 117f606c848SSatoshi Asami nostd = 1; 118f606c848SSatoshi Asami break; 119f606c848SSatoshi Asami case 'v': 120f606c848SSatoshi Asami verbose = 1; 121f606c848SSatoshi Asami break; 122b9ae52e3SPaul Richards default: 123571b472bSJordan K. Hubbard errx(1, "Usage: %s [-mrsv] [-f hints_file] [dir | file ...]", 12461f9ce8dSNate Williams __progname); 125b9ae52e3SPaul Richards break; 126b9ae52e3SPaul Richards } 127b9ae52e3SPaul Richards } 128b9ae52e3SPaul Richards 12980c71499SPeter Wemm dir_list = strdup(""); 13080c71499SPeter Wemm 131f606c848SSatoshi Asami if (justread || merge) { 132f606c848SSatoshi Asami if ((rval = readhints()) != 0) 133f606c848SSatoshi Asami return rval; 13480c71499SPeter Wemm } 13580c71499SPeter Wemm 13680c71499SPeter Wemm if (!nostd && !merge) 13780c71499SPeter Wemm std_search_path(); 13880c71499SPeter Wemm 139571b472bSJordan K. Hubbard /* Add any directories/files from the command line */ 140571b472bSJordan K. Hubbard if (!justread) { 141d66f9d22SJohn Polstra for (i = optind; i < argc; i++) { 142571b472bSJordan K. Hubbard struct stat stbuf; 143571b472bSJordan K. Hubbard 144571b472bSJordan K. Hubbard if (stat(argv[i], &stbuf) == -1) { 145d66f9d22SJohn Polstra warn("%s", argv[i]); 146d66f9d22SJohn Polstra rval = -1; 147571b472bSJordan K. Hubbard } else { 148571b472bSJordan K. Hubbard /* 149571b472bSJordan K. Hubbard * See if this is a directory-containing 150571b472bSJordan K. Hubbard * file instead of a directory 151571b472bSJordan K. Hubbard */ 152571b472bSJordan K. Hubbard if (S_ISREG(stbuf.st_mode)) 153571b472bSJordan K. Hubbard rval |= dofile(argv[i], 0); 154571b472bSJordan K. Hubbard else 15580c71499SPeter Wemm add_search_path(argv[i]); 156d66f9d22SJohn Polstra } 157d66f9d22SJohn Polstra } 158571b472bSJordan K. Hubbard } 15980c71499SPeter Wemm 16080c71499SPeter Wemm for (i = 0; i < n_search_dirs; i++) { 16180c71499SPeter Wemm char *cp = concat(dir_list, *dir_list?":":"", search_dirs[i]); 16280c71499SPeter Wemm free(dir_list); 16380c71499SPeter Wemm dir_list = cp; 16480c71499SPeter Wemm } 16580c71499SPeter Wemm 166f606c848SSatoshi Asami if (justread) { 167f606c848SSatoshi Asami listhints(); 168526195adSJordan K. Hubbard return 0; 169f606c848SSatoshi Asami } 170b9ae52e3SPaul Richards 171b9ae52e3SPaul Richards for (i = 0; i < n_search_dirs; i++) 17209e3d49dSJordan K. Hubbard rval |= dodir(search_dirs[i], 1); 173b9ae52e3SPaul Richards 174f606c848SSatoshi Asami rval |= buildhints(); 175b9ae52e3SPaul Richards 176b9ae52e3SPaul Richards return rval; 177b9ae52e3SPaul Richards } 178b9ae52e3SPaul Richards 179b9ae52e3SPaul Richards int 180571b472bSJordan K. Hubbard dofile(fname, silent) 181571b472bSJordan K. Hubbard char *fname; 182571b472bSJordan K. Hubbard int silent; 183571b472bSJordan K. Hubbard { 184571b472bSJordan K. Hubbard FILE *hfp; 185571b472bSJordan K. Hubbard char buf[MAXPATHLEN]; 186571b472bSJordan K. Hubbard int rval = 0; 187571b472bSJordan K. Hubbard char *cp, *sp; 188571b472bSJordan K. Hubbard 189571b472bSJordan K. Hubbard if ((hfp = fopen(fname, "r")) == NULL) { 190571b472bSJordan K. Hubbard warn("%s", fname); 191571b472bSJordan K. Hubbard return -1; 192571b472bSJordan K. Hubbard } 193571b472bSJordan K. Hubbard 194571b472bSJordan K. Hubbard while (fgets(buf, sizeof(buf), hfp)) { 195571b472bSJordan K. Hubbard cp = buf; 196571b472bSJordan K. Hubbard while (isspace(*cp)) 197571b472bSJordan K. Hubbard cp++; 198571b472bSJordan K. Hubbard if (*cp == '#' || *cp == '\0') 199571b472bSJordan K. Hubbard continue; 200571b472bSJordan K. Hubbard sp = cp; 201571b472bSJordan K. Hubbard while (!isspace(*cp) && *cp != '\0') 202571b472bSJordan K. Hubbard cp++; 203571b472bSJordan K. Hubbard 204571b472bSJordan K. Hubbard if (*cp != '\n') { 205571b472bSJordan K. Hubbard *cp = '\0'; 206571b472bSJordan K. Hubbard warnx("%s: Trailing characters ignored", sp); 207571b472bSJordan K. Hubbard } 208571b472bSJordan K. Hubbard 209571b472bSJordan K. Hubbard *cp = '\0'; 210571b472bSJordan K. Hubbard 211571b472bSJordan K. Hubbard rval |= dodir(sp, silent); 212571b472bSJordan K. Hubbard } 213571b472bSJordan K. Hubbard 214571b472bSJordan K. Hubbard (void)fclose(hfp); 215571b472bSJordan K. Hubbard return rval; 216571b472bSJordan K. Hubbard } 217571b472bSJordan K. Hubbard 218571b472bSJordan K. Hubbard int 21909e3d49dSJordan K. Hubbard dodir(dir, silent) 220b9ae52e3SPaul Richards char *dir; 22109e3d49dSJordan K. Hubbard int silent; 222b9ae52e3SPaul Richards { 223b9ae52e3SPaul Richards DIR *dd; 224b9ae52e3SPaul Richards struct dirent *dp; 2250f6b2cb3SPaul Traina char name[MAXPATHLEN]; 226b9ae52e3SPaul Richards int dewey[MAXDEWEY], ndewey; 227b9ae52e3SPaul Richards 228b9ae52e3SPaul Richards if ((dd = opendir(dir)) == NULL) { 229d66f9d22SJohn Polstra if (silent && errno == ENOENT) /* Ignore the error */ 230d66f9d22SJohn Polstra return 0; 231f606c848SSatoshi Asami warn("%s", dir); 232b9ae52e3SPaul Richards return -1; 233b9ae52e3SPaul Richards } 234b9ae52e3SPaul Richards 235b9ae52e3SPaul Richards while ((dp = readdir(dd)) != NULL) { 2360f6b2cb3SPaul Traina register int n; 2370f6b2cb3SPaul Traina register char *cp; 238b9ae52e3SPaul Richards 2390f6b2cb3SPaul Traina /* Check for `lib' prefix */ 2400f6b2cb3SPaul Traina if (dp->d_name[0] != 'l' || 2410f6b2cb3SPaul Traina dp->d_name[1] != 'i' || 2420f6b2cb3SPaul Traina dp->d_name[2] != 'b') 243b9ae52e3SPaul Richards continue; 244b9ae52e3SPaul Richards 2450f6b2cb3SPaul Traina /* Copy the entry minus prefix */ 2460f6b2cb3SPaul Traina (void)strcpy(name, dp->d_name + 3); 2470f6b2cb3SPaul Traina n = strlen(name); 2480f6b2cb3SPaul Traina if (n < 4) 2490f6b2cb3SPaul Traina continue; 2500f6b2cb3SPaul Traina 2510f6b2cb3SPaul Traina /* Find ".so." in name */ 2520f6b2cb3SPaul Traina for (cp = name + n - 4; cp > name; --cp) { 2530f6b2cb3SPaul Traina if (cp[0] == '.' && 2540f6b2cb3SPaul Traina cp[1] == 's' && 2550f6b2cb3SPaul Traina cp[2] == 'o' && 2560f6b2cb3SPaul Traina cp[3] == '.') 2570f6b2cb3SPaul Traina break; 2580f6b2cb3SPaul Traina } 2590f6b2cb3SPaul Traina if (cp <= name) 2600f6b2cb3SPaul Traina continue; 2610f6b2cb3SPaul Traina 2620f6b2cb3SPaul Traina *cp = '\0'; 2630f6b2cb3SPaul Traina if (!isdigit(*(cp+4))) 2640f6b2cb3SPaul Traina continue; 2650f6b2cb3SPaul Traina 2660f6b2cb3SPaul Traina bzero((caddr_t)dewey, sizeof(dewey)); 2670f6b2cb3SPaul Traina ndewey = getdewey(dewey, cp + 4); 268b9ae52e3SPaul Richards enter(dir, dp->d_name, name, dewey, ndewey); 269b9ae52e3SPaul Richards } 270b9ae52e3SPaul Richards 271571b472bSJordan K. Hubbard closedir(dd); 272b9ae52e3SPaul Richards return 0; 273b9ae52e3SPaul Richards } 274b9ae52e3SPaul Richards 275b9ae52e3SPaul Richards static void 276b9ae52e3SPaul Richards enter(dir, file, name, dewey, ndewey) 277b9ae52e3SPaul Richards char *dir, *file, *name; 278b9ae52e3SPaul Richards int dewey[], ndewey; 279b9ae52e3SPaul Richards { 280b9ae52e3SPaul Richards struct shlib_list *shp; 281b9ae52e3SPaul Richards 282b9ae52e3SPaul Richards for (shp = shlib_head; shp; shp = shp->next) { 283b9ae52e3SPaul Richards if (strcmp(name, shp->name) != 0 || major != shp->major) 284b9ae52e3SPaul Richards continue; 285b9ae52e3SPaul Richards 286b9ae52e3SPaul Richards /* Name matches existing entry */ 287b9ae52e3SPaul Richards if (cmpndewey(dewey, ndewey, shp->dewey, shp->ndewey) > 0) { 288b9ae52e3SPaul Richards 289b9ae52e3SPaul Richards /* Update this entry with higher versioned lib */ 290b9ae52e3SPaul Richards if (verbose) 291b9ae52e3SPaul Richards printf("Updating lib%s.%d.%d to %s/%s\n", 292b9ae52e3SPaul Richards shp->name, shp->major, shp->minor, 293b9ae52e3SPaul Richards dir, file); 294b9ae52e3SPaul Richards 295b9ae52e3SPaul Richards free(shp->name); 296b9ae52e3SPaul Richards shp->name = strdup(name); 297b9ae52e3SPaul Richards free(shp->path); 298b9ae52e3SPaul Richards shp->path = concat(dir, "/", file); 299b9ae52e3SPaul Richards bcopy(dewey, shp->dewey, sizeof(shp->dewey)); 300b9ae52e3SPaul Richards shp->ndewey = ndewey; 301b9ae52e3SPaul Richards } 302b9ae52e3SPaul Richards break; 303b9ae52e3SPaul Richards } 304b9ae52e3SPaul Richards 305b9ae52e3SPaul Richards if (shp) 306b9ae52e3SPaul Richards /* Name exists: older version or just updated */ 307b9ae52e3SPaul Richards return; 308b9ae52e3SPaul Richards 309b9ae52e3SPaul Richards /* Allocate new list element */ 310b9ae52e3SPaul Richards if (verbose) 311b9ae52e3SPaul Richards printf("Adding %s/%s\n", dir, file); 312b9ae52e3SPaul Richards 313b9ae52e3SPaul Richards shp = (struct shlib_list *)xmalloc(sizeof *shp); 314b9ae52e3SPaul Richards shp->name = strdup(name); 315b9ae52e3SPaul Richards shp->path = concat(dir, "/", file); 316b9ae52e3SPaul Richards bcopy(dewey, shp->dewey, MAXDEWEY); 317b9ae52e3SPaul Richards shp->ndewey = ndewey; 318b9ae52e3SPaul Richards shp->next = NULL; 319b9ae52e3SPaul Richards 320b9ae52e3SPaul Richards *shlib_tail = shp; 321b9ae52e3SPaul Richards shlib_tail = &shp->next; 322b9ae52e3SPaul Richards } 323b9ae52e3SPaul Richards 324b9ae52e3SPaul Richards 325b9ae52e3SPaul Richards int 326d5453ba5SJoerg Wunsch hinthash(cp, vmajor) 327b9ae52e3SPaul Richards char *cp; 328d5453ba5SJoerg Wunsch int vmajor; 329b9ae52e3SPaul Richards { 330b9ae52e3SPaul Richards int k = 0; 331b9ae52e3SPaul Richards 332b9ae52e3SPaul Richards while (*cp) 333b9ae52e3SPaul Richards k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff; 334b9ae52e3SPaul Richards 335b9ae52e3SPaul Richards k = (((k << 1) + (k >> 14)) ^ (vmajor*257)) & 0x3fff; 336b9ae52e3SPaul Richards 337b9ae52e3SPaul Richards return k; 338b9ae52e3SPaul Richards } 339b9ae52e3SPaul Richards 340b9ae52e3SPaul Richards int 341f606c848SSatoshi Asami buildhints() 342b9ae52e3SPaul Richards { 343b9ae52e3SPaul Richards struct hints_header hdr; 344b9ae52e3SPaul Richards struct hints_bucket *blist; 345b9ae52e3SPaul Richards struct shlib_list *shp; 346b9ae52e3SPaul Richards char *strtab; 347b9ae52e3SPaul Richards int i, n, str_index = 0; 348b9ae52e3SPaul Richards int strtab_sz = 0; /* Total length of strings */ 349b9ae52e3SPaul Richards int nhints = 0; /* Total number of hints */ 350b9ae52e3SPaul Richards int fd; 351b9ae52e3SPaul Richards char *tmpfile; 352b9ae52e3SPaul Richards 353b9ae52e3SPaul Richards for (shp = shlib_head; shp; shp = shp->next) { 354b9ae52e3SPaul Richards strtab_sz += 1 + strlen(shp->name); 355b9ae52e3SPaul Richards strtab_sz += 1 + strlen(shp->path); 356b9ae52e3SPaul Richards nhints++; 357b9ae52e3SPaul Richards } 358b9ae52e3SPaul Richards 359b9ae52e3SPaul Richards /* Fill hints file header */ 360b9ae52e3SPaul Richards hdr.hh_magic = HH_MAGIC; 36180c71499SPeter Wemm hdr.hh_version = LD_HINTS_VERSION_2; 362b9ae52e3SPaul Richards hdr.hh_nbucket = 1 * nhints; 363b9ae52e3SPaul Richards n = hdr.hh_nbucket * sizeof(struct hints_bucket); 364b9ae52e3SPaul Richards hdr.hh_hashtab = sizeof(struct hints_header); 365b9ae52e3SPaul Richards hdr.hh_strtab = hdr.hh_hashtab + n; 36680c71499SPeter Wemm hdr.hh_dirlist = strtab_sz; 36780c71499SPeter Wemm strtab_sz += 1 + strlen(dir_list); 368b9ae52e3SPaul Richards hdr.hh_strtab_sz = strtab_sz; 369b9ae52e3SPaul Richards hdr.hh_ehints = hdr.hh_strtab + hdr.hh_strtab_sz; 370b9ae52e3SPaul Richards 371b9ae52e3SPaul Richards if (verbose) 372526195adSJordan K. Hubbard printf("Totals: entries %d, buckets %ld, string size %d\n", 373b9ae52e3SPaul Richards nhints, hdr.hh_nbucket, strtab_sz); 374b9ae52e3SPaul Richards 375b9ae52e3SPaul Richards /* Allocate buckets and string table */ 376b9ae52e3SPaul Richards blist = (struct hints_bucket *)xmalloc(n); 377b9ae52e3SPaul Richards bzero((char *)blist, n); 378b9ae52e3SPaul Richards for (i = 0; i < hdr.hh_nbucket; i++) 379b9ae52e3SPaul Richards /* Empty all buckets */ 380b9ae52e3SPaul Richards blist[i].hi_next = -1; 381b9ae52e3SPaul Richards 382b9ae52e3SPaul Richards strtab = (char *)xmalloc(strtab_sz); 383b9ae52e3SPaul Richards 384b9ae52e3SPaul Richards /* Enter all */ 385b9ae52e3SPaul Richards for (shp = shlib_head; shp; shp = shp->next) { 386b9ae52e3SPaul Richards struct hints_bucket *bp; 387b9ae52e3SPaul Richards 388b9ae52e3SPaul Richards bp = blist + 389d5453ba5SJoerg Wunsch (hinthash(shp->name, shp->major) % hdr.hh_nbucket); 390b9ae52e3SPaul Richards 391b9ae52e3SPaul Richards if (bp->hi_pathx) { 392b9ae52e3SPaul Richards int i; 393b9ae52e3SPaul Richards 394b9ae52e3SPaul Richards for (i = 0; i < hdr.hh_nbucket; i++) { 395b9ae52e3SPaul Richards if (blist[i].hi_pathx == 0) 396b9ae52e3SPaul Richards break; 397b9ae52e3SPaul Richards } 398b9ae52e3SPaul Richards if (i == hdr.hh_nbucket) { 399f606c848SSatoshi Asami warnx("Bummer!"); 400b9ae52e3SPaul Richards return -1; 401b9ae52e3SPaul Richards } 402b9ae52e3SPaul Richards while (bp->hi_next != -1) 403b9ae52e3SPaul Richards bp = &blist[bp->hi_next]; 404b9ae52e3SPaul Richards bp->hi_next = i; 405b9ae52e3SPaul Richards bp = blist + i; 406b9ae52e3SPaul Richards } 407b9ae52e3SPaul Richards 408b9ae52e3SPaul Richards /* Insert strings in string table */ 409b9ae52e3SPaul Richards bp->hi_namex = str_index; 410b9ae52e3SPaul Richards strcpy(strtab + str_index, shp->name); 411b9ae52e3SPaul Richards str_index += 1 + strlen(shp->name); 412b9ae52e3SPaul Richards 413b9ae52e3SPaul Richards bp->hi_pathx = str_index; 414b9ae52e3SPaul Richards strcpy(strtab + str_index, shp->path); 415b9ae52e3SPaul Richards str_index += 1 + strlen(shp->path); 416b9ae52e3SPaul Richards 417b9ae52e3SPaul Richards /* Copy versions */ 418b9ae52e3SPaul Richards bcopy(shp->dewey, bp->hi_dewey, sizeof(bp->hi_dewey)); 419b9ae52e3SPaul Richards bp->hi_ndewey = shp->ndewey; 420b9ae52e3SPaul Richards } 421b9ae52e3SPaul Richards 42280c71499SPeter Wemm /* Copy search directories */ 42380c71499SPeter Wemm strcpy(strtab + str_index, dir_list); 42480c71499SPeter Wemm str_index += 1 + strlen(dir_list); 42580c71499SPeter Wemm 42680c71499SPeter Wemm /* Sanity check */ 42780c71499SPeter Wemm if (str_index != strtab_sz) { 42880c71499SPeter Wemm errx(1, "str_index(%d) != strtab_sz(%d)", str_index, strtab_sz); 42980c71499SPeter Wemm } 43080c71499SPeter Wemm 4317c6da7dcSJohn Polstra tmpfile = concat(hints_file, ".XXXXXX", ""); 43280c71499SPeter Wemm if ((tmpfile = mktemp(tmpfile)) == NULL) { 43380c71499SPeter Wemm warn("%s", tmpfile); 43480c71499SPeter Wemm return -1; 43580c71499SPeter Wemm } 43680c71499SPeter Wemm 43780c71499SPeter Wemm umask(0); /* Create with exact permissions */ 438b9ae52e3SPaul Richards if ((fd = open(tmpfile, O_RDWR|O_CREAT|O_TRUNC, 0444)) == -1) { 4397c6da7dcSJohn Polstra warn("%s", hints_file); 440b9ae52e3SPaul Richards return -1; 441b9ae52e3SPaul Richards } 442b9ae52e3SPaul Richards 44309e3d49dSJordan K. Hubbard if (write(fd, &hdr, sizeof(struct hints_header)) != 44409e3d49dSJordan K. Hubbard sizeof(struct hints_header)) { 4457c6da7dcSJohn Polstra warn("%s", hints_file); 44609e3d49dSJordan K. Hubbard return -1; 44709e3d49dSJordan K. Hubbard } 44809e3d49dSJordan K. Hubbard if (write(fd, blist, hdr.hh_nbucket * sizeof(struct hints_bucket)) != 44909e3d49dSJordan K. Hubbard hdr.hh_nbucket * sizeof(struct hints_bucket)) { 4507c6da7dcSJohn Polstra warn("%s", hints_file); 45109e3d49dSJordan K. Hubbard return -1; 45209e3d49dSJordan K. Hubbard } 45309e3d49dSJordan K. Hubbard if (write(fd, strtab, strtab_sz) != strtab_sz) { 4547c6da7dcSJohn Polstra warn("%s", hints_file); 45509e3d49dSJordan K. Hubbard return -1; 45609e3d49dSJordan K. Hubbard } 457b9ae52e3SPaul Richards if (close(fd) != 0) { 4587c6da7dcSJohn Polstra warn("%s", hints_file); 459b9ae52e3SPaul Richards return -1; 460b9ae52e3SPaul Richards } 461b9ae52e3SPaul Richards 46209e3d49dSJordan K. Hubbard /* Install it */ 4637c6da7dcSJohn Polstra if (unlink(hints_file) != 0 && errno != ENOENT) { 4647c6da7dcSJohn Polstra warn("%s", hints_file); 465b9ae52e3SPaul Richards return -1; 466b9ae52e3SPaul Richards } 467b9ae52e3SPaul Richards 4687c6da7dcSJohn Polstra if (rename(tmpfile, hints_file) != 0) { 4697c6da7dcSJohn Polstra warn("%s", hints_file); 470b9ae52e3SPaul Richards return -1; 471b9ae52e3SPaul Richards } 472b9ae52e3SPaul Richards 473b9ae52e3SPaul Richards return 0; 474b9ae52e3SPaul Richards } 475b9ae52e3SPaul Richards 476699e1b82SRich Murphey static int 477f606c848SSatoshi Asami readhints() 478b9ae52e3SPaul Richards { 479b9ae52e3SPaul Richards int fd; 480b9ae52e3SPaul Richards caddr_t addr; 481b9ae52e3SPaul Richards long msize; 482b9ae52e3SPaul Richards struct hints_header *hdr; 483b9ae52e3SPaul Richards struct hints_bucket *blist; 484b9ae52e3SPaul Richards char *strtab; 485f606c848SSatoshi Asami struct shlib_list *shp; 486b9ae52e3SPaul Richards int i; 487b9ae52e3SPaul Richards 4887c6da7dcSJohn Polstra if ((fd = open(hints_file, O_RDONLY, 0)) == -1) { 4897c6da7dcSJohn Polstra warn("%s", hints_file); 490b9ae52e3SPaul Richards return -1; 491b9ae52e3SPaul Richards } 492b9ae52e3SPaul Richards 49380c71499SPeter Wemm msize = PAGE_SIZE; 49461f9ce8dSNate Williams addr = mmap(0, msize, PROT_READ, MAP_COPY, fd, 0); 495b9ae52e3SPaul Richards 496b9ae52e3SPaul Richards if (addr == (caddr_t)-1) { 4977c6da7dcSJohn Polstra warn("%s", hints_file); 498b9ae52e3SPaul Richards return -1; 499b9ae52e3SPaul Richards } 500b9ae52e3SPaul Richards 501b9ae52e3SPaul Richards hdr = (struct hints_header *)addr; 502b9ae52e3SPaul Richards if (HH_BADMAG(*hdr)) { 503f606c848SSatoshi Asami warnx("%s: Bad magic: %o", 5047c6da7dcSJohn Polstra hints_file, hdr->hh_magic); 505b9ae52e3SPaul Richards return -1; 506b9ae52e3SPaul Richards } 507b9ae52e3SPaul Richards 50880c71499SPeter Wemm if (hdr->hh_version != LD_HINTS_VERSION_1 && 50980c71499SPeter Wemm hdr->hh_version != LD_HINTS_VERSION_2) { 510f606c848SSatoshi Asami warnx("Unsupported version: %d", hdr->hh_version); 511b9ae52e3SPaul Richards return -1; 512b9ae52e3SPaul Richards } 513b9ae52e3SPaul Richards 514b9ae52e3SPaul Richards if (hdr->hh_ehints > msize) { 515b9ae52e3SPaul Richards if (mmap(addr+msize, hdr->hh_ehints - msize, 51661f9ce8dSNate Williams PROT_READ, MAP_COPY|MAP_FIXED, 517b9ae52e3SPaul Richards fd, msize) != (caddr_t)(addr+msize)) { 518b9ae52e3SPaul Richards 5197c6da7dcSJohn Polstra warn("%s", hints_file); 520b9ae52e3SPaul Richards return -1; 521b9ae52e3SPaul Richards } 522b9ae52e3SPaul Richards } 523b9ae52e3SPaul Richards close(fd); 524b9ae52e3SPaul Richards 525b9ae52e3SPaul Richards blist = (struct hints_bucket *)(addr + hdr->hh_hashtab); 526b9ae52e3SPaul Richards strtab = (char *)(addr + hdr->hh_strtab); 527b9ae52e3SPaul Richards 528b9ae52e3SPaul Richards for (i = 0; i < hdr->hh_nbucket; i++) { 529b9ae52e3SPaul Richards struct hints_bucket *bp = &blist[i]; 530b9ae52e3SPaul Richards 531b9ae52e3SPaul Richards /* Sanity check */ 532b9ae52e3SPaul Richards if (bp->hi_namex >= hdr->hh_strtab_sz) { 533f606c848SSatoshi Asami warnx("Bad name index: %#x", bp->hi_namex); 534b9ae52e3SPaul Richards return -1; 535b9ae52e3SPaul Richards } 536b9ae52e3SPaul Richards if (bp->hi_pathx >= hdr->hh_strtab_sz) { 537f606c848SSatoshi Asami warnx("Bad path index: %#x", bp->hi_pathx); 538b9ae52e3SPaul Richards return -1; 539b9ae52e3SPaul Richards } 540b9ae52e3SPaul Richards 541f606c848SSatoshi Asami /* Allocate new list element */ 542f606c848SSatoshi Asami shp = (struct shlib_list *)xmalloc(sizeof *shp); 543f606c848SSatoshi Asami shp->name = strdup(strtab + bp->hi_namex); 544f606c848SSatoshi Asami shp->path = strdup(strtab + bp->hi_pathx); 545f606c848SSatoshi Asami bcopy(bp->hi_dewey, shp->dewey, sizeof(shp->dewey)); 546f606c848SSatoshi Asami shp->ndewey = bp->hi_ndewey; 547f606c848SSatoshi Asami shp->next = NULL; 548f606c848SSatoshi Asami 549f606c848SSatoshi Asami *shlib_tail = shp; 550f606c848SSatoshi Asami shlib_tail = &shp->next; 551b9ae52e3SPaul Richards } 55280c71499SPeter Wemm if (hdr->hh_version >= LD_HINTS_VERSION_2) 55380c71499SPeter Wemm add_search_path(strtab + hdr->hh_dirlist); 554b9ae52e3SPaul Richards 555b9ae52e3SPaul Richards return 0; 556b9ae52e3SPaul Richards } 557b9ae52e3SPaul Richards 558f606c848SSatoshi Asami static void 559f606c848SSatoshi Asami listhints() 560f606c848SSatoshi Asami { 561f606c848SSatoshi Asami struct shlib_list *shp; 562f606c848SSatoshi Asami int i; 563f606c848SSatoshi Asami 5647c6da7dcSJohn Polstra printf("%s:\n", hints_file); 56580c71499SPeter Wemm printf("\tsearch directories: %s\n", dir_list); 566f606c848SSatoshi Asami 567f606c848SSatoshi Asami for (i = 0, shp = shlib_head; shp; i++, shp = shp->next) 568f606c848SSatoshi Asami printf("\t%d:-l%s.%d.%d => %s\n", 569f606c848SSatoshi Asami i, shp->name, shp->major, shp->minor, shp->path); 570f606c848SSatoshi Asami 571f606c848SSatoshi Asami return; 572f606c848SSatoshi Asami } 573