1*1de7b4b8SPedro F. Giffuni /*- 2*1de7b4b8SPedro F. Giffuni * SPDX-License-Identifier: BSD-4-Clause 3*1de7b4b8SPedro F. Giffuni * 40f6b2cb3SPaul Traina * Copyright (c) 1993,1995 Paul Kranenburg 5b9ae52e3SPaul Richards * All rights reserved. 6b9ae52e3SPaul Richards * 7b9ae52e3SPaul Richards * Redistribution and use in source and binary forms, with or without 8b9ae52e3SPaul Richards * modification, are permitted provided that the following conditions 9b9ae52e3SPaul Richards * are met: 10b9ae52e3SPaul Richards * 1. Redistributions of source code must retain the above copyright 11b9ae52e3SPaul Richards * notice, this list of conditions and the following disclaimer. 12b9ae52e3SPaul Richards * 2. Redistributions in binary form must reproduce the above copyright 13b9ae52e3SPaul Richards * notice, this list of conditions and the following disclaimer in the 14b9ae52e3SPaul Richards * documentation and/or other materials provided with the distribution. 15b9ae52e3SPaul Richards * 3. All advertising materials mentioning features or use of this software 16b9ae52e3SPaul Richards * must display the following acknowledgement: 17b9ae52e3SPaul Richards * This product includes software developed by Paul Kranenburg. 18b9ae52e3SPaul Richards * 4. The name of the author may not be used to endorse or promote products 1909e3d49dSJordan K. Hubbard * derived from this software without specific prior written permission 20b9ae52e3SPaul Richards * 21b9ae52e3SPaul Richards * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22b9ae52e3SPaul Richards * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23b9ae52e3SPaul Richards * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24b9ae52e3SPaul Richards * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25b9ae52e3SPaul Richards * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26b9ae52e3SPaul Richards * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27b9ae52e3SPaul Richards * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28b9ae52e3SPaul Richards * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29b9ae52e3SPaul Richards * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30b9ae52e3SPaul Richards * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31b9ae52e3SPaul Richards */ 32b9ae52e3SPaul Richards 33b50d7faeSPhilippe Charnier #ifndef lint 34b50d7faeSPhilippe Charnier static const char rcsid[] = 357f3dea24SPeter Wemm "$FreeBSD$"; 36b50d7faeSPhilippe Charnier #endif /* not lint */ 37b50d7faeSPhilippe Charnier 38b9ae52e3SPaul Richards #include <sys/param.h> 39b9ae52e3SPaul Richards #include <sys/types.h> 40b9ae52e3SPaul Richards #include <sys/stat.h> 41b9ae52e3SPaul Richards #include <sys/mman.h> 42b9ae52e3SPaul Richards #include <a.out.h> 43b50d7faeSPhilippe Charnier #include <ctype.h> 44b50d7faeSPhilippe Charnier #include <dirent.h> 455e6220d9SDavid E. O'Brien #include <elf-hints.h> 46b50d7faeSPhilippe Charnier #include <err.h> 47b50d7faeSPhilippe Charnier #include <errno.h> 48b50d7faeSPhilippe Charnier #include <fcntl.h> 4966422f5bSPeter Wemm #include <sys/link_aout.h> 50699e1b82SRich Murphey #include <stdio.h> 51699e1b82SRich Murphey #include <stdlib.h> 52b9ae52e3SPaul Richards #include <string.h> 53699e1b82SRich Murphey #include <unistd.h> 54b9ae52e3SPaul Richards 55a565ca59SJohn Polstra #include "ldconfig.h" 5680c71499SPeter Wemm #include "shlib.h" 5780c71499SPeter Wemm #include "support.h" 5880c71499SPeter Wemm 597c6da7dcSJohn Polstra #if DEBUG 607c6da7dcSJohn Polstra /* test */ 617c6da7dcSJohn Polstra #undef _PATH_LD_HINTS 627c6da7dcSJohn Polstra #define _PATH_LD_HINTS "./ld.so.hints" 63a565ca59SJohn Polstra #undef _PATH_ELF_HINTS 64a565ca59SJohn Polstra #define _PATH_ELF_HINTS "./ld-elf.so.hints" 657c6da7dcSJohn Polstra #endif 66b9ae52e3SPaul Richards 67c905e45dSPeter Wemm #define _PATH_LD32_HINTS "/var/run/ld32.so.hints" 68c905e45dSPeter Wemm #define _PATH_ELF32_HINTS "/var/run/ld-elf32.so.hints" 694153c211SWarner Losh #define _PATH_ELFSOFT_HINTS "/var/run/ld-elf-soft.so.hints" 70c905e45dSPeter Wemm 71b9ae52e3SPaul Richards #undef major 72b9ae52e3SPaul Richards #undef minor 73b9ae52e3SPaul Richards 74b9ae52e3SPaul Richards static int verbose; 75b9ae52e3SPaul Richards static int nostd; 76b9ae52e3SPaul Richards static int justread; 77f606c848SSatoshi Asami static int merge; 78d4ba5766SPeter Wemm static int rescan; 7906eda379SXin LI static const char *hints_file; 80b9ae52e3SPaul Richards 81b9ae52e3SPaul Richards struct shlib_list { 82b9ae52e3SPaul Richards /* Internal list of shared libraries found */ 83b9ae52e3SPaul Richards char *name; 84b9ae52e3SPaul Richards char *path; 85b9ae52e3SPaul Richards int dewey[MAXDEWEY]; 86b9ae52e3SPaul Richards int ndewey; 87b9ae52e3SPaul Richards #define major dewey[0] 88b9ae52e3SPaul Richards #define minor dewey[1] 89b9ae52e3SPaul Richards struct shlib_list *next; 90b9ae52e3SPaul Richards }; 91b9ae52e3SPaul Richards 92b9ae52e3SPaul Richards static struct shlib_list *shlib_head = NULL, **shlib_tail = &shlib_head; 9380c71499SPeter Wemm static char *dir_list; 94b9ae52e3SPaul Richards 9585429990SWarner Losh static int buildhints(void); 9685429990SWarner Losh static int dodir(char *, int); 9785429990SWarner Losh int dofile(char *, int); 9885429990SWarner Losh static void enter(char *, char *, char *, int *, int); 9985429990SWarner Losh static void listhints(void); 10085429990SWarner Losh static int readhints(void); 10185429990SWarner Losh static void usage(void); 102b9ae52e3SPaul Richards 1032493aadaSWarner Losh /* 1042493aadaSWarner Losh * Note on aout/a.out support. 1052493aadaSWarner Losh * To properly support shared libraries for compat2x, which are a.out, we need 1062493aadaSWarner Losh * to support a.out here. As of 2013, bug reports are still coming in for this 1072493aadaSWarner Losh * feature (on amd64 no less), so we know it is still in use. 1082493aadaSWarner Losh */ 1092493aadaSWarner Losh 110b9ae52e3SPaul Richards int 11106eda379SXin LI main(int argc, char **argv) 112b9ae52e3SPaul Richards { 113b9ae52e3SPaul Richards int i, c; 114b9ae52e3SPaul Richards int rval = 0; 115c905e45dSPeter Wemm int is_aout = 0; 116c905e45dSPeter Wemm int is_32 = 0; 1174153c211SWarner Losh int is_soft = 0; 118b9ae52e3SPaul Richards 119c905e45dSPeter Wemm while (argc > 1) { 120c905e45dSPeter Wemm if (strcmp(argv[1], "-aout") == 0) { 12166422f5bSPeter Wemm is_aout = 1; 12266422f5bSPeter Wemm argc--; 12366422f5bSPeter Wemm argv++; 124c905e45dSPeter Wemm } else if (strcmp(argv[1], "-elf") == 0) { 125c905e45dSPeter Wemm is_aout = 0; 12666422f5bSPeter Wemm argc--; 12766422f5bSPeter Wemm argv++; 128c905e45dSPeter Wemm } else if (strcmp(argv[1], "-32") == 0) { 129c905e45dSPeter Wemm is_32 = 1; 130c905e45dSPeter Wemm argc--; 131c905e45dSPeter Wemm argv++; 1324153c211SWarner Losh } else if (strcmp(argv[1], "-soft") == 0) { 1334153c211SWarner Losh is_soft = 1; 1344153c211SWarner Losh argc--; 1354153c211SWarner Losh argv++; 136c905e45dSPeter Wemm } else { 137c905e45dSPeter Wemm break; 138c905e45dSPeter Wemm } 13966422f5bSPeter Wemm } 140cfa4d739SJohn Polstra 1414153c211SWarner Losh if (is_soft) 1424153c211SWarner Losh hints_file = _PATH_ELFSOFT_HINTS; /* Never will have a.out softfloat */ 1434153c211SWarner Losh else if (is_32) 144c905e45dSPeter Wemm hints_file = is_aout ? _PATH_LD32_HINTS : _PATH_ELF32_HINTS; 145c905e45dSPeter Wemm else 146cfa4d739SJohn Polstra hints_file = is_aout ? _PATH_LD_HINTS : _PATH_ELF_HINTS; 14797333b9eSJohn Polstra if (argc == 1) 14897333b9eSJohn Polstra rescan = 1; 149643dcf40SJohn Polstra else while((c = getopt(argc, argv, "Rf:imrsv")) != -1) { 150b9ae52e3SPaul Richards switch (c) { 151d4ba5766SPeter Wemm case 'R': 152d4ba5766SPeter Wemm rescan = 1; 153d4ba5766SPeter Wemm break; 1547c6da7dcSJohn Polstra case 'f': 1557c6da7dcSJohn Polstra hints_file = optarg; 1567c6da7dcSJohn Polstra break; 157643dcf40SJohn Polstra case 'i': 158643dcf40SJohn Polstra insecure = 1; 159643dcf40SJohn Polstra break; 160f606c848SSatoshi Asami case 'm': 161f606c848SSatoshi Asami merge = 1; 162b9ae52e3SPaul Richards break; 163b9ae52e3SPaul Richards case 'r': 164b9ae52e3SPaul Richards justread = 1; 165b9ae52e3SPaul Richards break; 166f606c848SSatoshi Asami case 's': 167f606c848SSatoshi Asami nostd = 1; 168f606c848SSatoshi Asami break; 169f606c848SSatoshi Asami case 'v': 170f606c848SSatoshi Asami verbose = 1; 171f606c848SSatoshi Asami break; 172b9ae52e3SPaul Richards default: 173b50d7faeSPhilippe Charnier usage(); 174b9ae52e3SPaul Richards break; 175b9ae52e3SPaul Richards } 176b9ae52e3SPaul Richards } 177b9ae52e3SPaul Richards 178cfa4d739SJohn Polstra if (!is_aout) { 179a565ca59SJohn Polstra if (justread) 180a565ca59SJohn Polstra list_elf_hints(hints_file); 181a565ca59SJohn Polstra else 182a565ca59SJohn Polstra update_elf_hints(hints_file, argc - optind, 183a565ca59SJohn Polstra argv + optind, merge || rescan); 184a565ca59SJohn Polstra return 0; 185a565ca59SJohn Polstra } 186a565ca59SJohn Polstra 187643dcf40SJohn Polstra /* Here begins the aout libs processing */ 18880c71499SPeter Wemm dir_list = strdup(""); 18980c71499SPeter Wemm 190d4ba5766SPeter Wemm if (justread || merge || rescan) { 191f606c848SSatoshi Asami if ((rval = readhints()) != 0) 192f606c848SSatoshi Asami return rval; 19380c71499SPeter Wemm } 19480c71499SPeter Wemm 195d4ba5766SPeter Wemm if (!nostd && !merge && !rescan) 19680c71499SPeter Wemm std_search_path(); 19780c71499SPeter Wemm 198571b472bSJordan K. Hubbard /* Add any directories/files from the command line */ 199571b472bSJordan K. Hubbard if (!justread) { 200d66f9d22SJohn Polstra for (i = optind; i < argc; i++) { 201571b472bSJordan K. Hubbard struct stat stbuf; 202571b472bSJordan K. Hubbard 203571b472bSJordan K. Hubbard if (stat(argv[i], &stbuf) == -1) { 204d66f9d22SJohn Polstra warn("%s", argv[i]); 205d66f9d22SJohn Polstra rval = -1; 206614d19caSJohn Polstra } else if (strcmp(argv[i], "/usr/lib") == 0) { 207cabb97dcSSøren Schmidt warnx("WARNING! '%s' can not be used", argv[i]); 208cabb97dcSSøren Schmidt rval = -1; 209614d19caSJohn Polstra } else { 210571b472bSJordan K. Hubbard /* 211571b472bSJordan K. Hubbard * See if this is a directory-containing 212571b472bSJordan K. Hubbard * file instead of a directory 213571b472bSJordan K. Hubbard */ 214571b472bSJordan K. Hubbard if (S_ISREG(stbuf.st_mode)) 215571b472bSJordan K. Hubbard rval |= dofile(argv[i], 0); 216571b472bSJordan K. Hubbard else 21780c71499SPeter Wemm add_search_path(argv[i]); 218d66f9d22SJohn Polstra } 219d66f9d22SJohn Polstra } 220571b472bSJordan K. Hubbard } 22180c71499SPeter Wemm 22280c71499SPeter Wemm for (i = 0; i < n_search_dirs; i++) { 22380c71499SPeter Wemm char *cp = concat(dir_list, *dir_list?":":"", search_dirs[i]); 22480c71499SPeter Wemm free(dir_list); 22580c71499SPeter Wemm dir_list = cp; 22680c71499SPeter Wemm } 22780c71499SPeter Wemm 228f606c848SSatoshi Asami if (justread) { 229f606c848SSatoshi Asami listhints(); 230526195adSJordan K. Hubbard return 0; 231f606c848SSatoshi Asami } 232b9ae52e3SPaul Richards 233b9ae52e3SPaul Richards for (i = 0; i < n_search_dirs; i++) 23409e3d49dSJordan K. Hubbard rval |= dodir(search_dirs[i], 1); 235b9ae52e3SPaul Richards 236f606c848SSatoshi Asami rval |= buildhints(); 237b9ae52e3SPaul Richards 238b9ae52e3SPaul Richards return rval; 239b9ae52e3SPaul Richards } 240b9ae52e3SPaul Richards 241b50d7faeSPhilippe Charnier static void 242f709df34SEd Schouten usage(void) 243b50d7faeSPhilippe Charnier { 244b50d7faeSPhilippe Charnier fprintf(stderr, 2456efabadaSJohn Baldwin "usage: ldconfig [-32] [-aout | -elf] [-Rimrsv] [-f hints_file] [directory | file ...]\n"); 246b50d7faeSPhilippe Charnier exit(1); 247b50d7faeSPhilippe Charnier } 248b50d7faeSPhilippe Charnier 249b9ae52e3SPaul Richards int 250f709df34SEd Schouten dofile(char *fname, int silent) 251571b472bSJordan K. Hubbard { 252571b472bSJordan K. Hubbard FILE *hfp; 253571b472bSJordan K. Hubbard char buf[MAXPATHLEN]; 254571b472bSJordan K. Hubbard int rval = 0; 255571b472bSJordan K. Hubbard char *cp, *sp; 256571b472bSJordan K. Hubbard 257571b472bSJordan K. Hubbard if ((hfp = fopen(fname, "r")) == NULL) { 258571b472bSJordan K. Hubbard warn("%s", fname); 259571b472bSJordan K. Hubbard return -1; 260571b472bSJordan K. Hubbard } 261571b472bSJordan K. Hubbard 262571b472bSJordan K. Hubbard while (fgets(buf, sizeof(buf), hfp)) { 263571b472bSJordan K. Hubbard cp = buf; 264571b472bSJordan K. Hubbard while (isspace(*cp)) 265571b472bSJordan K. Hubbard cp++; 266571b472bSJordan K. Hubbard if (*cp == '#' || *cp == '\0') 267571b472bSJordan K. Hubbard continue; 268571b472bSJordan K. Hubbard sp = cp; 269571b472bSJordan K. Hubbard while (!isspace(*cp) && *cp != '\0') 270571b472bSJordan K. Hubbard cp++; 271571b472bSJordan K. Hubbard 272571b472bSJordan K. Hubbard if (*cp != '\n') { 273571b472bSJordan K. Hubbard *cp = '\0'; 274b50d7faeSPhilippe Charnier warnx("%s: trailing characters ignored", sp); 275571b472bSJordan K. Hubbard } 276571b472bSJordan K. Hubbard 277571b472bSJordan K. Hubbard *cp = '\0'; 278571b472bSJordan K. Hubbard 279571b472bSJordan K. Hubbard rval |= dodir(sp, silent); 280571b472bSJordan K. Hubbard } 281571b472bSJordan K. Hubbard 282571b472bSJordan K. Hubbard (void)fclose(hfp); 283571b472bSJordan K. Hubbard return rval; 284571b472bSJordan K. Hubbard } 285571b472bSJordan K. Hubbard 286571b472bSJordan K. Hubbard int 287f709df34SEd Schouten dodir(char *dir, int silent) 288b9ae52e3SPaul Richards { 289b9ae52e3SPaul Richards DIR *dd; 290b9ae52e3SPaul Richards struct dirent *dp; 2910f6b2cb3SPaul Traina char name[MAXPATHLEN]; 292b9ae52e3SPaul Richards int dewey[MAXDEWEY], ndewey; 293b9ae52e3SPaul Richards 294b9ae52e3SPaul Richards if ((dd = opendir(dir)) == NULL) { 295d66f9d22SJohn Polstra if (silent && errno == ENOENT) /* Ignore the error */ 296d66f9d22SJohn Polstra return 0; 297f606c848SSatoshi Asami warn("%s", dir); 298b9ae52e3SPaul Richards return -1; 299b9ae52e3SPaul Richards } 300b9ae52e3SPaul Richards 301b9ae52e3SPaul Richards while ((dp = readdir(dd)) != NULL) { 3023d438ad6SDavid E. O'Brien int n; 3033d438ad6SDavid E. O'Brien char *cp; 304b9ae52e3SPaul Richards 3050f6b2cb3SPaul Traina /* Check for `lib' prefix */ 3060f6b2cb3SPaul Traina if (dp->d_name[0] != 'l' || 3070f6b2cb3SPaul Traina dp->d_name[1] != 'i' || 3080f6b2cb3SPaul Traina dp->d_name[2] != 'b') 309b9ae52e3SPaul Richards continue; 310b9ae52e3SPaul Richards 3110f6b2cb3SPaul Traina /* Copy the entry minus prefix */ 3120f6b2cb3SPaul Traina (void)strcpy(name, dp->d_name + 3); 3130f6b2cb3SPaul Traina n = strlen(name); 3140f6b2cb3SPaul Traina if (n < 4) 3150f6b2cb3SPaul Traina continue; 3160f6b2cb3SPaul Traina 3170f6b2cb3SPaul Traina /* Find ".so." in name */ 3180f6b2cb3SPaul Traina for (cp = name + n - 4; cp > name; --cp) { 3190f6b2cb3SPaul Traina if (cp[0] == '.' && 3200f6b2cb3SPaul Traina cp[1] == 's' && 3210f6b2cb3SPaul Traina cp[2] == 'o' && 3220f6b2cb3SPaul Traina cp[3] == '.') 3230f6b2cb3SPaul Traina break; 3240f6b2cb3SPaul Traina } 3250f6b2cb3SPaul Traina if (cp <= name) 3260f6b2cb3SPaul Traina continue; 3270f6b2cb3SPaul Traina 3280f6b2cb3SPaul Traina *cp = '\0'; 3290f6b2cb3SPaul Traina if (!isdigit(*(cp+4))) 3300f6b2cb3SPaul Traina continue; 3310f6b2cb3SPaul Traina 3320f6b2cb3SPaul Traina bzero((caddr_t)dewey, sizeof(dewey)); 3330f6b2cb3SPaul Traina ndewey = getdewey(dewey, cp + 4); 3345f8d88ddSJohn Polstra if (ndewey < 2) 3355f8d88ddSJohn Polstra continue; 336b9ae52e3SPaul Richards enter(dir, dp->d_name, name, dewey, ndewey); 337b9ae52e3SPaul Richards } 338b9ae52e3SPaul Richards 339571b472bSJordan K. Hubbard closedir(dd); 340b9ae52e3SPaul Richards return 0; 341b9ae52e3SPaul Richards } 342b9ae52e3SPaul Richards 343b9ae52e3SPaul Richards static void 344f709df34SEd Schouten enter(char *dir, char *file, char *name, int dewey[], int ndewey) 345b9ae52e3SPaul Richards { 346b9ae52e3SPaul Richards struct shlib_list *shp; 347b9ae52e3SPaul Richards 348b9ae52e3SPaul Richards for (shp = shlib_head; shp; shp = shp->next) { 349b9ae52e3SPaul Richards if (strcmp(name, shp->name) != 0 || major != shp->major) 350b9ae52e3SPaul Richards continue; 351b9ae52e3SPaul Richards 352b9ae52e3SPaul Richards /* Name matches existing entry */ 353b9ae52e3SPaul Richards if (cmpndewey(dewey, ndewey, shp->dewey, shp->ndewey) > 0) { 354b9ae52e3SPaul Richards 355b9ae52e3SPaul Richards /* Update this entry with higher versioned lib */ 356b9ae52e3SPaul Richards if (verbose) 357b9ae52e3SPaul Richards printf("Updating lib%s.%d.%d to %s/%s\n", 358b9ae52e3SPaul Richards shp->name, shp->major, shp->minor, 359b9ae52e3SPaul Richards dir, file); 360b9ae52e3SPaul Richards 361b9ae52e3SPaul Richards free(shp->name); 362b9ae52e3SPaul Richards shp->name = strdup(name); 363b9ae52e3SPaul Richards free(shp->path); 364b9ae52e3SPaul Richards shp->path = concat(dir, "/", file); 365b9ae52e3SPaul Richards bcopy(dewey, shp->dewey, sizeof(shp->dewey)); 366b9ae52e3SPaul Richards shp->ndewey = ndewey; 367b9ae52e3SPaul Richards } 368b9ae52e3SPaul Richards break; 369b9ae52e3SPaul Richards } 370b9ae52e3SPaul Richards 371b9ae52e3SPaul Richards if (shp) 372b9ae52e3SPaul Richards /* Name exists: older version or just updated */ 373b9ae52e3SPaul Richards return; 374b9ae52e3SPaul Richards 375b9ae52e3SPaul Richards /* Allocate new list element */ 376b9ae52e3SPaul Richards if (verbose) 377b9ae52e3SPaul Richards printf("Adding %s/%s\n", dir, file); 378b9ae52e3SPaul Richards 379b9ae52e3SPaul Richards shp = (struct shlib_list *)xmalloc(sizeof *shp); 380b9ae52e3SPaul Richards shp->name = strdup(name); 381b9ae52e3SPaul Richards shp->path = concat(dir, "/", file); 3827d85b9aaSColin Percival bcopy(dewey, shp->dewey, sizeof(shp->dewey)); 383b9ae52e3SPaul Richards shp->ndewey = ndewey; 384b9ae52e3SPaul Richards shp->next = NULL; 385b9ae52e3SPaul Richards 386b9ae52e3SPaul Richards *shlib_tail = shp; 387b9ae52e3SPaul Richards shlib_tail = &shp->next; 388b9ae52e3SPaul Richards } 389b9ae52e3SPaul Richards 390b9ae52e3SPaul Richards 39106eda379SXin LI static int 39206eda379SXin LI hinthash(char *cp, int vmajor) 393b9ae52e3SPaul Richards { 394b9ae52e3SPaul Richards int k = 0; 395b9ae52e3SPaul Richards 396b9ae52e3SPaul Richards while (*cp) 397b9ae52e3SPaul Richards k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff; 398b9ae52e3SPaul Richards 399b9ae52e3SPaul Richards k = (((k << 1) + (k >> 14)) ^ (vmajor*257)) & 0x3fff; 400b9ae52e3SPaul Richards 401b9ae52e3SPaul Richards return k; 402b9ae52e3SPaul Richards } 403b9ae52e3SPaul Richards 404b9ae52e3SPaul Richards int 405f709df34SEd Schouten buildhints(void) 406b9ae52e3SPaul Richards { 407b9ae52e3SPaul Richards struct hints_header hdr; 408b9ae52e3SPaul Richards struct hints_bucket *blist; 409b9ae52e3SPaul Richards struct shlib_list *shp; 410b9ae52e3SPaul Richards char *strtab; 411b9ae52e3SPaul Richards int i, n, str_index = 0; 412b9ae52e3SPaul Richards int strtab_sz = 0; /* Total length of strings */ 413b9ae52e3SPaul Richards int nhints = 0; /* Total number of hints */ 414b9ae52e3SPaul Richards int fd; 415665fc054SXin LI char *tmpfilename; 416b9ae52e3SPaul Richards 417b9ae52e3SPaul Richards for (shp = shlib_head; shp; shp = shp->next) { 418b9ae52e3SPaul Richards strtab_sz += 1 + strlen(shp->name); 419b9ae52e3SPaul Richards strtab_sz += 1 + strlen(shp->path); 420b9ae52e3SPaul Richards nhints++; 421b9ae52e3SPaul Richards } 422b9ae52e3SPaul Richards 423b9ae52e3SPaul Richards /* Fill hints file header */ 424b9ae52e3SPaul Richards hdr.hh_magic = HH_MAGIC; 42580c71499SPeter Wemm hdr.hh_version = LD_HINTS_VERSION_2; 426b9ae52e3SPaul Richards hdr.hh_nbucket = 1 * nhints; 427b9ae52e3SPaul Richards n = hdr.hh_nbucket * sizeof(struct hints_bucket); 428b9ae52e3SPaul Richards hdr.hh_hashtab = sizeof(struct hints_header); 429b9ae52e3SPaul Richards hdr.hh_strtab = hdr.hh_hashtab + n; 43080c71499SPeter Wemm hdr.hh_dirlist = strtab_sz; 43180c71499SPeter Wemm strtab_sz += 1 + strlen(dir_list); 432b9ae52e3SPaul Richards hdr.hh_strtab_sz = strtab_sz; 433b9ae52e3SPaul Richards hdr.hh_ehints = hdr.hh_strtab + hdr.hh_strtab_sz; 434b9ae52e3SPaul Richards 435b9ae52e3SPaul Richards if (verbose) 436526195adSJordan K. Hubbard printf("Totals: entries %d, buckets %ld, string size %d\n", 437ab845347SBruce Evans nhints, (long)hdr.hh_nbucket, strtab_sz); 438b9ae52e3SPaul Richards 439b9ae52e3SPaul Richards /* Allocate buckets and string table */ 440b9ae52e3SPaul Richards blist = (struct hints_bucket *)xmalloc(n); 441b9ae52e3SPaul Richards bzero((char *)blist, n); 442b9ae52e3SPaul Richards for (i = 0; i < hdr.hh_nbucket; i++) 443b9ae52e3SPaul Richards /* Empty all buckets */ 444b9ae52e3SPaul Richards blist[i].hi_next = -1; 445b9ae52e3SPaul Richards 446b9ae52e3SPaul Richards strtab = (char *)xmalloc(strtab_sz); 447b9ae52e3SPaul Richards 448b9ae52e3SPaul Richards /* Enter all */ 449b9ae52e3SPaul Richards for (shp = shlib_head; shp; shp = shp->next) { 450b9ae52e3SPaul Richards struct hints_bucket *bp; 451b9ae52e3SPaul Richards 452b9ae52e3SPaul Richards bp = blist + 453d5453ba5SJoerg Wunsch (hinthash(shp->name, shp->major) % hdr.hh_nbucket); 454b9ae52e3SPaul Richards 455b9ae52e3SPaul Richards if (bp->hi_pathx) { 45606eda379SXin LI int j; 457b9ae52e3SPaul Richards 45806eda379SXin LI for (j = 0; j < hdr.hh_nbucket; j++) { 45906eda379SXin LI if (blist[j].hi_pathx == 0) 460b9ae52e3SPaul Richards break; 461b9ae52e3SPaul Richards } 46206eda379SXin LI if (j == hdr.hh_nbucket) { 463b50d7faeSPhilippe Charnier warnx("bummer!"); 464b9ae52e3SPaul Richards return -1; 465b9ae52e3SPaul Richards } 466b9ae52e3SPaul Richards while (bp->hi_next != -1) 467b9ae52e3SPaul Richards bp = &blist[bp->hi_next]; 46806eda379SXin LI bp->hi_next = j; 46906eda379SXin LI bp = blist + j; 470b9ae52e3SPaul Richards } 471b9ae52e3SPaul Richards 472b9ae52e3SPaul Richards /* Insert strings in string table */ 473b9ae52e3SPaul Richards bp->hi_namex = str_index; 474b9ae52e3SPaul Richards strcpy(strtab + str_index, shp->name); 475b9ae52e3SPaul Richards str_index += 1 + strlen(shp->name); 476b9ae52e3SPaul Richards 477b9ae52e3SPaul Richards bp->hi_pathx = str_index; 478b9ae52e3SPaul Richards strcpy(strtab + str_index, shp->path); 479b9ae52e3SPaul Richards str_index += 1 + strlen(shp->path); 480b9ae52e3SPaul Richards 481b9ae52e3SPaul Richards /* Copy versions */ 482b9ae52e3SPaul Richards bcopy(shp->dewey, bp->hi_dewey, sizeof(bp->hi_dewey)); 483b9ae52e3SPaul Richards bp->hi_ndewey = shp->ndewey; 484b9ae52e3SPaul Richards } 485b9ae52e3SPaul Richards 48680c71499SPeter Wemm /* Copy search directories */ 48780c71499SPeter Wemm strcpy(strtab + str_index, dir_list); 48880c71499SPeter Wemm str_index += 1 + strlen(dir_list); 48980c71499SPeter Wemm 49080c71499SPeter Wemm /* Sanity check */ 49180c71499SPeter Wemm if (str_index != strtab_sz) { 49280c71499SPeter Wemm errx(1, "str_index(%d) != strtab_sz(%d)", str_index, strtab_sz); 49380c71499SPeter Wemm } 49480c71499SPeter Wemm 495665fc054SXin LI tmpfilename = concat(hints_file, ".XXXXXXXXXX", ""); 49616bd17ceSKris Kennaway umask(0); /* Create with exact permissions */ 497665fc054SXin LI if ((fd = mkstemp(tmpfilename)) == -1) { 498665fc054SXin LI warn("%s", tmpfilename); 49980c71499SPeter Wemm return -1; 50080c71499SPeter Wemm } 50116bd17ceSKris Kennaway fchmod(fd, 0444); 502b9ae52e3SPaul Richards 50309e3d49dSJordan K. Hubbard if (write(fd, &hdr, sizeof(struct hints_header)) != 50409e3d49dSJordan K. Hubbard sizeof(struct hints_header)) { 5057c6da7dcSJohn Polstra warn("%s", hints_file); 50609e3d49dSJordan K. Hubbard return -1; 50709e3d49dSJordan K. Hubbard } 50874b67e84SXin LI if (write(fd, blist, hdr.hh_nbucket * sizeof(*blist)) != 50974b67e84SXin LI (ssize_t)(hdr.hh_nbucket * sizeof(*blist))) { 5107c6da7dcSJohn Polstra warn("%s", hints_file); 51109e3d49dSJordan K. Hubbard return -1; 51209e3d49dSJordan K. Hubbard } 51309e3d49dSJordan K. Hubbard if (write(fd, strtab, strtab_sz) != strtab_sz) { 5147c6da7dcSJohn Polstra warn("%s", hints_file); 51509e3d49dSJordan K. Hubbard return -1; 51609e3d49dSJordan K. Hubbard } 517b9ae52e3SPaul Richards if (close(fd) != 0) { 5187c6da7dcSJohn Polstra warn("%s", hints_file); 519b9ae52e3SPaul Richards return -1; 520b9ae52e3SPaul Richards } 521b9ae52e3SPaul Richards 52209e3d49dSJordan K. Hubbard /* Install it */ 5237c6da7dcSJohn Polstra if (unlink(hints_file) != 0 && errno != ENOENT) { 5247c6da7dcSJohn Polstra warn("%s", hints_file); 525b9ae52e3SPaul Richards return -1; 526b9ae52e3SPaul Richards } 527b9ae52e3SPaul Richards 528665fc054SXin LI if (rename(tmpfilename, hints_file) != 0) { 5297c6da7dcSJohn Polstra warn("%s", hints_file); 530b9ae52e3SPaul Richards return -1; 531b9ae52e3SPaul Richards } 532b9ae52e3SPaul Richards 533b9ae52e3SPaul Richards return 0; 534b9ae52e3SPaul Richards } 535b9ae52e3SPaul Richards 536699e1b82SRich Murphey static int 537f709df34SEd Schouten readhints(void) 538b9ae52e3SPaul Richards { 539b9ae52e3SPaul Richards int fd; 540614d19caSJohn Polstra void *addr; 541614d19caSJohn Polstra long fsize; 542b9ae52e3SPaul Richards long msize; 543b9ae52e3SPaul Richards struct hints_header *hdr; 544b9ae52e3SPaul Richards struct hints_bucket *blist; 545b9ae52e3SPaul Richards char *strtab; 546f606c848SSatoshi Asami struct shlib_list *shp; 547b9ae52e3SPaul Richards int i; 548b9ae52e3SPaul Richards 5497c6da7dcSJohn Polstra if ((fd = open(hints_file, O_RDONLY, 0)) == -1) { 5507c6da7dcSJohn Polstra warn("%s", hints_file); 551b9ae52e3SPaul Richards return -1; 552b9ae52e3SPaul Richards } 553b9ae52e3SPaul Richards 55480c71499SPeter Wemm msize = PAGE_SIZE; 555be8f91d3SEdward Tomasz Napierala addr = mmap(0, msize, PROT_READ, MAP_PRIVATE, fd, 0); 556b9ae52e3SPaul Richards 557614d19caSJohn Polstra if (addr == MAP_FAILED) { 5587c6da7dcSJohn Polstra warn("%s", hints_file); 559b9ae52e3SPaul Richards return -1; 560b9ae52e3SPaul Richards } 561b9ae52e3SPaul Richards 562b9ae52e3SPaul Richards hdr = (struct hints_header *)addr; 563b9ae52e3SPaul Richards if (HH_BADMAG(*hdr)) { 564ab845347SBruce Evans warnx("%s: bad magic: %lo", hints_file, 565ab845347SBruce Evans (unsigned long)hdr->hh_magic); 566b9ae52e3SPaul Richards return -1; 567b9ae52e3SPaul Richards } 568b9ae52e3SPaul Richards 56980c71499SPeter Wemm if (hdr->hh_version != LD_HINTS_VERSION_1 && 57080c71499SPeter Wemm hdr->hh_version != LD_HINTS_VERSION_2) { 571ab845347SBruce Evans warnx("unsupported version: %ld", (long)hdr->hh_version); 572b9ae52e3SPaul Richards return -1; 573b9ae52e3SPaul Richards } 574b9ae52e3SPaul Richards 575b9ae52e3SPaul Richards if (hdr->hh_ehints > msize) { 576614d19caSJohn Polstra fsize = hdr->hh_ehints; 577614d19caSJohn Polstra munmap(addr, msize); 578be8f91d3SEdward Tomasz Napierala addr = mmap(0, fsize, PROT_READ, MAP_PRIVATE, fd, 0); 579614d19caSJohn Polstra if (addr == MAP_FAILED) { 5807c6da7dcSJohn Polstra warn("%s", hints_file); 581b9ae52e3SPaul Richards return -1; 582b9ae52e3SPaul Richards } 583614d19caSJohn Polstra hdr = (struct hints_header *)addr; 584b9ae52e3SPaul Richards } 585b9ae52e3SPaul Richards close(fd); 586b9ae52e3SPaul Richards 5874eae39bfSStefan Farfeleder strtab = (char *)addr + hdr->hh_strtab; 588b9ae52e3SPaul Richards 589d4ba5766SPeter Wemm if (hdr->hh_version >= LD_HINTS_VERSION_2) 590d4ba5766SPeter Wemm add_search_path(strtab + hdr->hh_dirlist); 591d4ba5766SPeter Wemm else if (rescan) 592d4ba5766SPeter Wemm errx(1, "%s too old and does not contain the search path", 593d4ba5766SPeter Wemm hints_file); 594d4ba5766SPeter Wemm 595d4ba5766SPeter Wemm if (rescan) 596d4ba5766SPeter Wemm return 0; 597d4ba5766SPeter Wemm 59874b67e84SXin LI blist = malloc(sizeof(*blist) * hdr->hh_nbucket); 59906eda379SXin LI if (blist == NULL) 60006eda379SXin LI err(1, "readhints"); 60106eda379SXin LI memcpy(blist, (char *)addr + hdr->hh_hashtab, 60274b67e84SXin LI sizeof(*blist) * hdr->hh_nbucket); 60306eda379SXin LI 60406eda379SXin LI 605b9ae52e3SPaul Richards for (i = 0; i < hdr->hh_nbucket; i++) { 606b9ae52e3SPaul Richards struct hints_bucket *bp = &blist[i]; 607b9ae52e3SPaul Richards 608b9ae52e3SPaul Richards /* Sanity check */ 609b9ae52e3SPaul Richards if (bp->hi_namex >= hdr->hh_strtab_sz) { 610b50d7faeSPhilippe Charnier warnx("bad name index: %#x", bp->hi_namex); 61106eda379SXin LI free(blist); 612b9ae52e3SPaul Richards return -1; 613b9ae52e3SPaul Richards } 614b9ae52e3SPaul Richards if (bp->hi_pathx >= hdr->hh_strtab_sz) { 615b50d7faeSPhilippe Charnier warnx("bad path index: %#x", bp->hi_pathx); 61606eda379SXin LI free(blist); 617b9ae52e3SPaul Richards return -1; 618b9ae52e3SPaul Richards } 619b9ae52e3SPaul Richards 620f606c848SSatoshi Asami /* Allocate new list element */ 621f606c848SSatoshi Asami shp = (struct shlib_list *)xmalloc(sizeof *shp); 622f606c848SSatoshi Asami shp->name = strdup(strtab + bp->hi_namex); 623f606c848SSatoshi Asami shp->path = strdup(strtab + bp->hi_pathx); 624f606c848SSatoshi Asami bcopy(bp->hi_dewey, shp->dewey, sizeof(shp->dewey)); 625f606c848SSatoshi Asami shp->ndewey = bp->hi_ndewey; 626f606c848SSatoshi Asami shp->next = NULL; 627f606c848SSatoshi Asami 628f606c848SSatoshi Asami *shlib_tail = shp; 629f606c848SSatoshi Asami shlib_tail = &shp->next; 630b9ae52e3SPaul Richards } 631b9ae52e3SPaul Richards 63206eda379SXin LI free(blist); 633b9ae52e3SPaul Richards return 0; 634b9ae52e3SPaul Richards } 635b9ae52e3SPaul Richards 636f606c848SSatoshi Asami static void 637f709df34SEd Schouten listhints(void) 638f606c848SSatoshi Asami { 639f606c848SSatoshi Asami struct shlib_list *shp; 640f606c848SSatoshi Asami int i; 641f606c848SSatoshi Asami 6427c6da7dcSJohn Polstra printf("%s:\n", hints_file); 64380c71499SPeter Wemm printf("\tsearch directories: %s\n", dir_list); 644f606c848SSatoshi Asami 645f606c848SSatoshi Asami for (i = 0, shp = shlib_head; shp; i++, shp = shp->next) 646f606c848SSatoshi Asami printf("\t%d:-l%s.%d.%d => %s\n", 647f606c848SSatoshi Asami i, shp->name, shp->major, shp->minor, shp->path); 648f606c848SSatoshi Asami 649f606c848SSatoshi Asami return; 650f606c848SSatoshi Asami } 651