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[] = 33614d19caSJohn Polstra "$Id: ldconfig.c,v 1.26 1998/09/05 16:20:15 jdp Exp $"; 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> 48699e1b82SRich Murphey #include <stdio.h> 49699e1b82SRich Murphey #include <stdlib.h> 50b9ae52e3SPaul Richards #include <string.h> 51699e1b82SRich Murphey #include <unistd.h> 52b9ae52e3SPaul Richards 53a565ca59SJohn Polstra #include "ldconfig.h" 5480c71499SPeter Wemm #include "shlib.h" 5580c71499SPeter Wemm #include "support.h" 5680c71499SPeter Wemm 577c6da7dcSJohn Polstra #if DEBUG 587c6da7dcSJohn Polstra /* test */ 597c6da7dcSJohn Polstra #undef _PATH_LD_HINTS 607c6da7dcSJohn Polstra #define _PATH_LD_HINTS "./ld.so.hints" 61a565ca59SJohn Polstra #undef _PATH_ELF_HINTS 62a565ca59SJohn Polstra #define _PATH_ELF_HINTS "./ld-elf.so.hints" 637c6da7dcSJohn Polstra #endif 64b9ae52e3SPaul Richards 65b9ae52e3SPaul Richards #undef major 66b9ae52e3SPaul Richards #undef minor 67b9ae52e3SPaul Richards 68a565ca59SJohn Polstra enum obj_format { Unknown, Aout, Elf }; 69a565ca59SJohn Polstra 70a565ca59SJohn Polstra #ifndef DEFAULT_FORMAT 71a565ca59SJohn Polstra #ifdef __ELF__ 72a565ca59SJohn Polstra #define DEFAULT_FORMAT Elf 73a565ca59SJohn Polstra #else 74a565ca59SJohn Polstra #define DEFAULT_FORMAT Aout 75a565ca59SJohn Polstra #endif 76a565ca59SJohn Polstra #endif 77a565ca59SJohn Polstra 78b9ae52e3SPaul Richards static int verbose; 79b9ae52e3SPaul Richards static int nostd; 80b9ae52e3SPaul Richards static int justread; 81f606c848SSatoshi Asami static int merge; 82d4ba5766SPeter Wemm static int rescan; 83a565ca59SJohn Polstra static char *hints_file; 84b9ae52e3SPaul Richards 85b9ae52e3SPaul Richards struct shlib_list { 86b9ae52e3SPaul Richards /* Internal list of shared libraries found */ 87b9ae52e3SPaul Richards char *name; 88b9ae52e3SPaul Richards char *path; 89b9ae52e3SPaul Richards int dewey[MAXDEWEY]; 90b9ae52e3SPaul Richards int ndewey; 91b9ae52e3SPaul Richards #define major dewey[0] 92b9ae52e3SPaul Richards #define minor dewey[1] 93b9ae52e3SPaul Richards struct shlib_list *next; 94b9ae52e3SPaul Richards }; 95b9ae52e3SPaul Richards 96b9ae52e3SPaul Richards static struct shlib_list *shlib_head = NULL, **shlib_tail = &shlib_head; 9780c71499SPeter Wemm static char *dir_list; 98b9ae52e3SPaul Richards 99a565ca59SJohn Polstra static int buildhints __P((void)); 10009e3d49dSJordan K. Hubbard static int dodir __P((char *, int)); 101b50d7faeSPhilippe Charnier int dofile __P((char *, int)); 102a565ca59SJohn Polstra static void enter __P((char *, char *, char *, int *, int)); 103a565ca59SJohn Polstra static enum obj_format getobjfmt __P((int *, char **)); 104f606c848SSatoshi Asami static void listhints __P((void)); 105a565ca59SJohn Polstra static int readhints __P((void)); 106b50d7faeSPhilippe Charnier static void usage __P((void)); 107b9ae52e3SPaul Richards 108b9ae52e3SPaul Richards int 109b9ae52e3SPaul Richards main(argc, argv) 110b9ae52e3SPaul Richards int argc; 111b9ae52e3SPaul Richards char *argv[]; 112b9ae52e3SPaul Richards { 113b9ae52e3SPaul Richards int i, c; 114b9ae52e3SPaul Richards int rval = 0; 115a565ca59SJohn Polstra enum obj_format fmt; 116b9ae52e3SPaul Richards 117a565ca59SJohn Polstra fmt = getobjfmt(&argc, argv); 118a565ca59SJohn Polstra hints_file = fmt == Aout ? _PATH_LD_HINTS : _PATH_ELF_HINTS; 119b50d7faeSPhilippe Charnier while ((c = getopt(argc, argv, "Rf:mrsv")) != -1) { 120b9ae52e3SPaul Richards switch (c) { 121d4ba5766SPeter Wemm case 'R': 122d4ba5766SPeter Wemm rescan = 1; 123d4ba5766SPeter Wemm break; 1247c6da7dcSJohn Polstra case 'f': 1257c6da7dcSJohn Polstra hints_file = optarg; 1267c6da7dcSJohn Polstra break; 127f606c848SSatoshi Asami case 'm': 128f606c848SSatoshi Asami merge = 1; 129b9ae52e3SPaul Richards break; 130b9ae52e3SPaul Richards case 'r': 131b9ae52e3SPaul Richards justread = 1; 132b9ae52e3SPaul Richards break; 133f606c848SSatoshi Asami case 's': 134f606c848SSatoshi Asami nostd = 1; 135f606c848SSatoshi Asami break; 136f606c848SSatoshi Asami case 'v': 137f606c848SSatoshi Asami verbose = 1; 138f606c848SSatoshi Asami break; 139b9ae52e3SPaul Richards default: 140b50d7faeSPhilippe Charnier usage(); 141b9ae52e3SPaul Richards break; 142b9ae52e3SPaul Richards } 143b9ae52e3SPaul Richards } 144b9ae52e3SPaul Richards 145a565ca59SJohn Polstra if (fmt == Elf) { 146a565ca59SJohn Polstra if (justread) 147a565ca59SJohn Polstra list_elf_hints(hints_file); 148a565ca59SJohn Polstra else 149a565ca59SJohn Polstra update_elf_hints(hints_file, argc - optind, 150a565ca59SJohn Polstra argv + optind, merge || rescan); 151a565ca59SJohn Polstra return 0; 152a565ca59SJohn Polstra } 153a565ca59SJohn Polstra 15480c71499SPeter Wemm dir_list = strdup(""); 15580c71499SPeter Wemm 156d4ba5766SPeter Wemm if (justread || merge || rescan) { 157f606c848SSatoshi Asami if ((rval = readhints()) != 0) 158f606c848SSatoshi Asami return rval; 15980c71499SPeter Wemm } 16080c71499SPeter Wemm 161d4ba5766SPeter Wemm if (!nostd && !merge && !rescan) 16280c71499SPeter Wemm std_search_path(); 16380c71499SPeter Wemm 164571b472bSJordan K. Hubbard /* Add any directories/files from the command line */ 165571b472bSJordan K. Hubbard if (!justread) { 166d66f9d22SJohn Polstra for (i = optind; i < argc; i++) { 167571b472bSJordan K. Hubbard struct stat stbuf; 168571b472bSJordan K. Hubbard 169571b472bSJordan K. Hubbard if (stat(argv[i], &stbuf) == -1) { 170d66f9d22SJohn Polstra warn("%s", argv[i]); 171d66f9d22SJohn Polstra rval = -1; 172614d19caSJohn Polstra } else if (strcmp(argv[i], "/usr/lib") == 0) { 173cabb97dcSSøren Schmidt warnx("WARNING! '%s' can not be used", argv[i]); 174cabb97dcSSøren Schmidt rval = -1; 175614d19caSJohn Polstra } else { 176571b472bSJordan K. Hubbard /* 177571b472bSJordan K. Hubbard * See if this is a directory-containing 178571b472bSJordan K. Hubbard * file instead of a directory 179571b472bSJordan K. Hubbard */ 180571b472bSJordan K. Hubbard if (S_ISREG(stbuf.st_mode)) 181571b472bSJordan K. Hubbard rval |= dofile(argv[i], 0); 182571b472bSJordan K. Hubbard else 18380c71499SPeter Wemm add_search_path(argv[i]); 184d66f9d22SJohn Polstra } 185d66f9d22SJohn Polstra } 186571b472bSJordan K. Hubbard } 18780c71499SPeter Wemm 18880c71499SPeter Wemm for (i = 0; i < n_search_dirs; i++) { 18980c71499SPeter Wemm char *cp = concat(dir_list, *dir_list?":":"", search_dirs[i]); 19080c71499SPeter Wemm free(dir_list); 19180c71499SPeter Wemm dir_list = cp; 19280c71499SPeter Wemm } 19380c71499SPeter Wemm 194f606c848SSatoshi Asami if (justread) { 195f606c848SSatoshi Asami listhints(); 196526195adSJordan K. Hubbard return 0; 197f606c848SSatoshi Asami } 198b9ae52e3SPaul Richards 199b9ae52e3SPaul Richards for (i = 0; i < n_search_dirs; i++) 20009e3d49dSJordan K. Hubbard rval |= dodir(search_dirs[i], 1); 201b9ae52e3SPaul Richards 202f606c848SSatoshi Asami rval |= buildhints(); 203b9ae52e3SPaul Richards 204b9ae52e3SPaul Richards return rval; 205b9ae52e3SPaul Richards } 206b9ae52e3SPaul Richards 207a565ca59SJohn Polstra static enum obj_format 208a565ca59SJohn Polstra getobjfmt(argcp, argv) 209a565ca59SJohn Polstra int *argcp; 210a565ca59SJohn Polstra char **argv; 211a565ca59SJohn Polstra { 212a565ca59SJohn Polstra enum obj_format fmt; 213a565ca59SJohn Polstra char **src, **dst; 214a565ca59SJohn Polstra const char *env; 215a565ca59SJohn Polstra FILE *fp; 216a565ca59SJohn Polstra 217a565ca59SJohn Polstra fmt = Unknown; 218a565ca59SJohn Polstra 219a565ca59SJohn Polstra /* Scan for "-aout" or "-elf" arguments, deleting them as we go. */ 220a565ca59SJohn Polstra for (dst = src = argv + 1; *src != NULL; src++) { 221a565ca59SJohn Polstra if (strcmp(*src, "-aout") == 0) 222a565ca59SJohn Polstra fmt = Aout; 223a565ca59SJohn Polstra else if (strcmp(*src, "-elf") == 0) 224a565ca59SJohn Polstra fmt = Elf; 225a565ca59SJohn Polstra else 226a565ca59SJohn Polstra *dst++ = *src; 227a565ca59SJohn Polstra } 228a565ca59SJohn Polstra *dst = NULL; 229a565ca59SJohn Polstra *argcp -= src - dst; 230a565ca59SJohn Polstra if (fmt != Unknown) 231a565ca59SJohn Polstra return fmt; 232a565ca59SJohn Polstra 233a565ca59SJohn Polstra /* Check the OBJFORMAT environment variable. */ 234a565ca59SJohn Polstra if ((env = getenv("OBJFORMAT")) != NULL) { 235a565ca59SJohn Polstra if (strcmp(env, "aout") == 0) 236a565ca59SJohn Polstra return Aout; 237a565ca59SJohn Polstra else if (strcmp(env, "elf") == 0) 238a565ca59SJohn Polstra return Elf; 239a565ca59SJohn Polstra } 240a565ca59SJohn Polstra 241a565ca59SJohn Polstra /* Take a look at "/etc/objformat". */ 242a565ca59SJohn Polstra if ((fp = fopen("/etc/objformat", "r")) != NULL) { 243a565ca59SJohn Polstra char buf[1024]; 244a565ca59SJohn Polstra 245a565ca59SJohn Polstra while (fgets(buf, sizeof buf, fp) != NULL) { 246a565ca59SJohn Polstra if (strcmp(buf, "OBJFORMAT=aout\n") == 0) 247a565ca59SJohn Polstra fmt = Aout; 248a565ca59SJohn Polstra else if (strcmp(buf, "OBJFORMAT=elf\n") == 0) 249a565ca59SJohn Polstra fmt = Elf; 250a565ca59SJohn Polstra else 251a565ca59SJohn Polstra warnx("Unrecognized line in /etc/objformat: %s", 252a565ca59SJohn Polstra buf); 253a565ca59SJohn Polstra } 254a565ca59SJohn Polstra fclose(fp); 255a565ca59SJohn Polstra } 256a565ca59SJohn Polstra if (fmt != Unknown) 257a565ca59SJohn Polstra return fmt; 258a565ca59SJohn Polstra 259a565ca59SJohn Polstra /* As a last resort, use the compiled in default. */ 260a565ca59SJohn Polstra return DEFAULT_FORMAT; 261a565ca59SJohn Polstra } 262a565ca59SJohn Polstra 263b50d7faeSPhilippe Charnier static void 264b50d7faeSPhilippe Charnier usage() 265b50d7faeSPhilippe Charnier { 266b50d7faeSPhilippe Charnier fprintf(stderr, 267b50d7faeSPhilippe Charnier "usage: ldconfig [-Rmrsv] [-f hints_file] [dir | file ...]\n"); 268b50d7faeSPhilippe Charnier exit(1); 269b50d7faeSPhilippe Charnier } 270b50d7faeSPhilippe Charnier 271b9ae52e3SPaul Richards int 272571b472bSJordan K. Hubbard dofile(fname, silent) 273571b472bSJordan K. Hubbard char *fname; 274571b472bSJordan K. Hubbard int silent; 275571b472bSJordan K. Hubbard { 276571b472bSJordan K. Hubbard FILE *hfp; 277571b472bSJordan K. Hubbard char buf[MAXPATHLEN]; 278571b472bSJordan K. Hubbard int rval = 0; 279571b472bSJordan K. Hubbard char *cp, *sp; 280571b472bSJordan K. Hubbard 281571b472bSJordan K. Hubbard if ((hfp = fopen(fname, "r")) == NULL) { 282571b472bSJordan K. Hubbard warn("%s", fname); 283571b472bSJordan K. Hubbard return -1; 284571b472bSJordan K. Hubbard } 285571b472bSJordan K. Hubbard 286571b472bSJordan K. Hubbard while (fgets(buf, sizeof(buf), hfp)) { 287571b472bSJordan K. Hubbard cp = buf; 288571b472bSJordan K. Hubbard while (isspace(*cp)) 289571b472bSJordan K. Hubbard cp++; 290571b472bSJordan K. Hubbard if (*cp == '#' || *cp == '\0') 291571b472bSJordan K. Hubbard continue; 292571b472bSJordan K. Hubbard sp = cp; 293571b472bSJordan K. Hubbard while (!isspace(*cp) && *cp != '\0') 294571b472bSJordan K. Hubbard cp++; 295571b472bSJordan K. Hubbard 296571b472bSJordan K. Hubbard if (*cp != '\n') { 297571b472bSJordan K. Hubbard *cp = '\0'; 298b50d7faeSPhilippe Charnier warnx("%s: trailing characters ignored", sp); 299571b472bSJordan K. Hubbard } 300571b472bSJordan K. Hubbard 301571b472bSJordan K. Hubbard *cp = '\0'; 302571b472bSJordan K. Hubbard 303571b472bSJordan K. Hubbard rval |= dodir(sp, silent); 304571b472bSJordan K. Hubbard } 305571b472bSJordan K. Hubbard 306571b472bSJordan K. Hubbard (void)fclose(hfp); 307571b472bSJordan K. Hubbard return rval; 308571b472bSJordan K. Hubbard } 309571b472bSJordan K. Hubbard 310571b472bSJordan K. Hubbard int 31109e3d49dSJordan K. Hubbard dodir(dir, silent) 312b9ae52e3SPaul Richards char *dir; 31309e3d49dSJordan K. Hubbard int silent; 314b9ae52e3SPaul Richards { 315b9ae52e3SPaul Richards DIR *dd; 316b9ae52e3SPaul Richards struct dirent *dp; 3170f6b2cb3SPaul Traina char name[MAXPATHLEN]; 318b9ae52e3SPaul Richards int dewey[MAXDEWEY], ndewey; 319b9ae52e3SPaul Richards 320b9ae52e3SPaul Richards if ((dd = opendir(dir)) == NULL) { 321d66f9d22SJohn Polstra if (silent && errno == ENOENT) /* Ignore the error */ 322d66f9d22SJohn Polstra return 0; 323f606c848SSatoshi Asami warn("%s", dir); 324b9ae52e3SPaul Richards return -1; 325b9ae52e3SPaul Richards } 326b9ae52e3SPaul Richards 327b9ae52e3SPaul Richards while ((dp = readdir(dd)) != NULL) { 3280f6b2cb3SPaul Traina register int n; 3290f6b2cb3SPaul Traina register char *cp; 330b9ae52e3SPaul Richards 3310f6b2cb3SPaul Traina /* Check for `lib' prefix */ 3320f6b2cb3SPaul Traina if (dp->d_name[0] != 'l' || 3330f6b2cb3SPaul Traina dp->d_name[1] != 'i' || 3340f6b2cb3SPaul Traina dp->d_name[2] != 'b') 335b9ae52e3SPaul Richards continue; 336b9ae52e3SPaul Richards 3370f6b2cb3SPaul Traina /* Copy the entry minus prefix */ 3380f6b2cb3SPaul Traina (void)strcpy(name, dp->d_name + 3); 3390f6b2cb3SPaul Traina n = strlen(name); 3400f6b2cb3SPaul Traina if (n < 4) 3410f6b2cb3SPaul Traina continue; 3420f6b2cb3SPaul Traina 3430f6b2cb3SPaul Traina /* Find ".so." in name */ 3440f6b2cb3SPaul Traina for (cp = name + n - 4; cp > name; --cp) { 3450f6b2cb3SPaul Traina if (cp[0] == '.' && 3460f6b2cb3SPaul Traina cp[1] == 's' && 3470f6b2cb3SPaul Traina cp[2] == 'o' && 3480f6b2cb3SPaul Traina cp[3] == '.') 3490f6b2cb3SPaul Traina break; 3500f6b2cb3SPaul Traina } 3510f6b2cb3SPaul Traina if (cp <= name) 3520f6b2cb3SPaul Traina continue; 3530f6b2cb3SPaul Traina 3540f6b2cb3SPaul Traina *cp = '\0'; 3550f6b2cb3SPaul Traina if (!isdigit(*(cp+4))) 3560f6b2cb3SPaul Traina continue; 3570f6b2cb3SPaul Traina 3580f6b2cb3SPaul Traina bzero((caddr_t)dewey, sizeof(dewey)); 3590f6b2cb3SPaul Traina ndewey = getdewey(dewey, cp + 4); 3605f8d88ddSJohn Polstra if (ndewey < 2) 3615f8d88ddSJohn Polstra continue; 362b9ae52e3SPaul Richards enter(dir, dp->d_name, name, dewey, ndewey); 363b9ae52e3SPaul Richards } 364b9ae52e3SPaul Richards 365571b472bSJordan K. Hubbard closedir(dd); 366b9ae52e3SPaul Richards return 0; 367b9ae52e3SPaul Richards } 368b9ae52e3SPaul Richards 369b9ae52e3SPaul Richards static void 370b9ae52e3SPaul Richards enter(dir, file, name, dewey, ndewey) 371b9ae52e3SPaul Richards char *dir, *file, *name; 372b9ae52e3SPaul Richards int dewey[], ndewey; 373b9ae52e3SPaul Richards { 374b9ae52e3SPaul Richards struct shlib_list *shp; 375b9ae52e3SPaul Richards 376b9ae52e3SPaul Richards for (shp = shlib_head; shp; shp = shp->next) { 377b9ae52e3SPaul Richards if (strcmp(name, shp->name) != 0 || major != shp->major) 378b9ae52e3SPaul Richards continue; 379b9ae52e3SPaul Richards 380b9ae52e3SPaul Richards /* Name matches existing entry */ 381b9ae52e3SPaul Richards if (cmpndewey(dewey, ndewey, shp->dewey, shp->ndewey) > 0) { 382b9ae52e3SPaul Richards 383b9ae52e3SPaul Richards /* Update this entry with higher versioned lib */ 384b9ae52e3SPaul Richards if (verbose) 385b9ae52e3SPaul Richards printf("Updating lib%s.%d.%d to %s/%s\n", 386b9ae52e3SPaul Richards shp->name, shp->major, shp->minor, 387b9ae52e3SPaul Richards dir, file); 388b9ae52e3SPaul Richards 389b9ae52e3SPaul Richards free(shp->name); 390b9ae52e3SPaul Richards shp->name = strdup(name); 391b9ae52e3SPaul Richards free(shp->path); 392b9ae52e3SPaul Richards shp->path = concat(dir, "/", file); 393b9ae52e3SPaul Richards bcopy(dewey, shp->dewey, sizeof(shp->dewey)); 394b9ae52e3SPaul Richards shp->ndewey = ndewey; 395b9ae52e3SPaul Richards } 396b9ae52e3SPaul Richards break; 397b9ae52e3SPaul Richards } 398b9ae52e3SPaul Richards 399b9ae52e3SPaul Richards if (shp) 400b9ae52e3SPaul Richards /* Name exists: older version or just updated */ 401b9ae52e3SPaul Richards return; 402b9ae52e3SPaul Richards 403b9ae52e3SPaul Richards /* Allocate new list element */ 404b9ae52e3SPaul Richards if (verbose) 405b9ae52e3SPaul Richards printf("Adding %s/%s\n", dir, file); 406b9ae52e3SPaul Richards 407b9ae52e3SPaul Richards shp = (struct shlib_list *)xmalloc(sizeof *shp); 408b9ae52e3SPaul Richards shp->name = strdup(name); 409b9ae52e3SPaul Richards shp->path = concat(dir, "/", file); 410b9ae52e3SPaul Richards bcopy(dewey, shp->dewey, MAXDEWEY); 411b9ae52e3SPaul Richards shp->ndewey = ndewey; 412b9ae52e3SPaul Richards shp->next = NULL; 413b9ae52e3SPaul Richards 414b9ae52e3SPaul Richards *shlib_tail = shp; 415b9ae52e3SPaul Richards shlib_tail = &shp->next; 416b9ae52e3SPaul Richards } 417b9ae52e3SPaul Richards 418b9ae52e3SPaul Richards 419b9ae52e3SPaul Richards int 420d5453ba5SJoerg Wunsch hinthash(cp, vmajor) 421b9ae52e3SPaul Richards char *cp; 422d5453ba5SJoerg Wunsch int vmajor; 423b9ae52e3SPaul Richards { 424b9ae52e3SPaul Richards int k = 0; 425b9ae52e3SPaul Richards 426b9ae52e3SPaul Richards while (*cp) 427b9ae52e3SPaul Richards k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff; 428b9ae52e3SPaul Richards 429b9ae52e3SPaul Richards k = (((k << 1) + (k >> 14)) ^ (vmajor*257)) & 0x3fff; 430b9ae52e3SPaul Richards 431b9ae52e3SPaul Richards return k; 432b9ae52e3SPaul Richards } 433b9ae52e3SPaul Richards 434b9ae52e3SPaul Richards int 435f606c848SSatoshi Asami buildhints() 436b9ae52e3SPaul Richards { 437b9ae52e3SPaul Richards struct hints_header hdr; 438b9ae52e3SPaul Richards struct hints_bucket *blist; 439b9ae52e3SPaul Richards struct shlib_list *shp; 440b9ae52e3SPaul Richards char *strtab; 441b9ae52e3SPaul Richards int i, n, str_index = 0; 442b9ae52e3SPaul Richards int strtab_sz = 0; /* Total length of strings */ 443b9ae52e3SPaul Richards int nhints = 0; /* Total number of hints */ 444b9ae52e3SPaul Richards int fd; 445b9ae52e3SPaul Richards char *tmpfile; 446b9ae52e3SPaul Richards 447b9ae52e3SPaul Richards for (shp = shlib_head; shp; shp = shp->next) { 448b9ae52e3SPaul Richards strtab_sz += 1 + strlen(shp->name); 449b9ae52e3SPaul Richards strtab_sz += 1 + strlen(shp->path); 450b9ae52e3SPaul Richards nhints++; 451b9ae52e3SPaul Richards } 452b9ae52e3SPaul Richards 453b9ae52e3SPaul Richards /* Fill hints file header */ 454b9ae52e3SPaul Richards hdr.hh_magic = HH_MAGIC; 45580c71499SPeter Wemm hdr.hh_version = LD_HINTS_VERSION_2; 456b9ae52e3SPaul Richards hdr.hh_nbucket = 1 * nhints; 457b9ae52e3SPaul Richards n = hdr.hh_nbucket * sizeof(struct hints_bucket); 458b9ae52e3SPaul Richards hdr.hh_hashtab = sizeof(struct hints_header); 459b9ae52e3SPaul Richards hdr.hh_strtab = hdr.hh_hashtab + n; 46080c71499SPeter Wemm hdr.hh_dirlist = strtab_sz; 46180c71499SPeter Wemm strtab_sz += 1 + strlen(dir_list); 462b9ae52e3SPaul Richards hdr.hh_strtab_sz = strtab_sz; 463b9ae52e3SPaul Richards hdr.hh_ehints = hdr.hh_strtab + hdr.hh_strtab_sz; 464b9ae52e3SPaul Richards 465b9ae52e3SPaul Richards if (verbose) 466526195adSJordan K. Hubbard printf("Totals: entries %d, buckets %ld, string size %d\n", 467ab845347SBruce Evans nhints, (long)hdr.hh_nbucket, strtab_sz); 468b9ae52e3SPaul Richards 469b9ae52e3SPaul Richards /* Allocate buckets and string table */ 470b9ae52e3SPaul Richards blist = (struct hints_bucket *)xmalloc(n); 471b9ae52e3SPaul Richards bzero((char *)blist, n); 472b9ae52e3SPaul Richards for (i = 0; i < hdr.hh_nbucket; i++) 473b9ae52e3SPaul Richards /* Empty all buckets */ 474b9ae52e3SPaul Richards blist[i].hi_next = -1; 475b9ae52e3SPaul Richards 476b9ae52e3SPaul Richards strtab = (char *)xmalloc(strtab_sz); 477b9ae52e3SPaul Richards 478b9ae52e3SPaul Richards /* Enter all */ 479b9ae52e3SPaul Richards for (shp = shlib_head; shp; shp = shp->next) { 480b9ae52e3SPaul Richards struct hints_bucket *bp; 481b9ae52e3SPaul Richards 482b9ae52e3SPaul Richards bp = blist + 483d5453ba5SJoerg Wunsch (hinthash(shp->name, shp->major) % hdr.hh_nbucket); 484b9ae52e3SPaul Richards 485b9ae52e3SPaul Richards if (bp->hi_pathx) { 486b9ae52e3SPaul Richards int i; 487b9ae52e3SPaul Richards 488b9ae52e3SPaul Richards for (i = 0; i < hdr.hh_nbucket; i++) { 489b9ae52e3SPaul Richards if (blist[i].hi_pathx == 0) 490b9ae52e3SPaul Richards break; 491b9ae52e3SPaul Richards } 492b9ae52e3SPaul Richards if (i == hdr.hh_nbucket) { 493b50d7faeSPhilippe Charnier warnx("bummer!"); 494b9ae52e3SPaul Richards return -1; 495b9ae52e3SPaul Richards } 496b9ae52e3SPaul Richards while (bp->hi_next != -1) 497b9ae52e3SPaul Richards bp = &blist[bp->hi_next]; 498b9ae52e3SPaul Richards bp->hi_next = i; 499b9ae52e3SPaul Richards bp = blist + i; 500b9ae52e3SPaul Richards } 501b9ae52e3SPaul Richards 502b9ae52e3SPaul Richards /* Insert strings in string table */ 503b9ae52e3SPaul Richards bp->hi_namex = str_index; 504b9ae52e3SPaul Richards strcpy(strtab + str_index, shp->name); 505b9ae52e3SPaul Richards str_index += 1 + strlen(shp->name); 506b9ae52e3SPaul Richards 507b9ae52e3SPaul Richards bp->hi_pathx = str_index; 508b9ae52e3SPaul Richards strcpy(strtab + str_index, shp->path); 509b9ae52e3SPaul Richards str_index += 1 + strlen(shp->path); 510b9ae52e3SPaul Richards 511b9ae52e3SPaul Richards /* Copy versions */ 512b9ae52e3SPaul Richards bcopy(shp->dewey, bp->hi_dewey, sizeof(bp->hi_dewey)); 513b9ae52e3SPaul Richards bp->hi_ndewey = shp->ndewey; 514b9ae52e3SPaul Richards } 515b9ae52e3SPaul Richards 51680c71499SPeter Wemm /* Copy search directories */ 51780c71499SPeter Wemm strcpy(strtab + str_index, dir_list); 51880c71499SPeter Wemm str_index += 1 + strlen(dir_list); 51980c71499SPeter Wemm 52080c71499SPeter Wemm /* Sanity check */ 52180c71499SPeter Wemm if (str_index != strtab_sz) { 52280c71499SPeter Wemm errx(1, "str_index(%d) != strtab_sz(%d)", str_index, strtab_sz); 52380c71499SPeter Wemm } 52480c71499SPeter Wemm 5257c6da7dcSJohn Polstra tmpfile = concat(hints_file, ".XXXXXX", ""); 52680c71499SPeter Wemm if ((tmpfile = mktemp(tmpfile)) == NULL) { 52780c71499SPeter Wemm warn("%s", tmpfile); 52880c71499SPeter Wemm return -1; 52980c71499SPeter Wemm } 53080c71499SPeter Wemm 53180c71499SPeter Wemm umask(0); /* Create with exact permissions */ 532b9ae52e3SPaul Richards if ((fd = open(tmpfile, O_RDWR|O_CREAT|O_TRUNC, 0444)) == -1) { 5337c6da7dcSJohn Polstra warn("%s", hints_file); 534b9ae52e3SPaul Richards return -1; 535b9ae52e3SPaul Richards } 536b9ae52e3SPaul Richards 53709e3d49dSJordan K. Hubbard if (write(fd, &hdr, sizeof(struct hints_header)) != 53809e3d49dSJordan K. Hubbard sizeof(struct hints_header)) { 5397c6da7dcSJohn Polstra warn("%s", hints_file); 54009e3d49dSJordan K. Hubbard return -1; 54109e3d49dSJordan K. Hubbard } 54209e3d49dSJordan K. Hubbard if (write(fd, blist, hdr.hh_nbucket * sizeof(struct hints_bucket)) != 54309e3d49dSJordan K. Hubbard hdr.hh_nbucket * sizeof(struct hints_bucket)) { 5447c6da7dcSJohn Polstra warn("%s", hints_file); 54509e3d49dSJordan K. Hubbard return -1; 54609e3d49dSJordan K. Hubbard } 54709e3d49dSJordan K. Hubbard if (write(fd, strtab, strtab_sz) != strtab_sz) { 5487c6da7dcSJohn Polstra warn("%s", hints_file); 54909e3d49dSJordan K. Hubbard return -1; 55009e3d49dSJordan K. Hubbard } 551b9ae52e3SPaul Richards if (close(fd) != 0) { 5527c6da7dcSJohn Polstra warn("%s", hints_file); 553b9ae52e3SPaul Richards return -1; 554b9ae52e3SPaul Richards } 555b9ae52e3SPaul Richards 55609e3d49dSJordan K. Hubbard /* Install it */ 5577c6da7dcSJohn Polstra if (unlink(hints_file) != 0 && errno != ENOENT) { 5587c6da7dcSJohn Polstra warn("%s", hints_file); 559b9ae52e3SPaul Richards return -1; 560b9ae52e3SPaul Richards } 561b9ae52e3SPaul Richards 5627c6da7dcSJohn Polstra if (rename(tmpfile, hints_file) != 0) { 5637c6da7dcSJohn Polstra warn("%s", hints_file); 564b9ae52e3SPaul Richards return -1; 565b9ae52e3SPaul Richards } 566b9ae52e3SPaul Richards 567b9ae52e3SPaul Richards return 0; 568b9ae52e3SPaul Richards } 569b9ae52e3SPaul Richards 570699e1b82SRich Murphey static int 571f606c848SSatoshi Asami readhints() 572b9ae52e3SPaul Richards { 573b9ae52e3SPaul Richards int fd; 574614d19caSJohn Polstra void *addr; 575614d19caSJohn Polstra long fsize; 576b9ae52e3SPaul Richards long msize; 577b9ae52e3SPaul Richards struct hints_header *hdr; 578b9ae52e3SPaul Richards struct hints_bucket *blist; 579b9ae52e3SPaul Richards char *strtab; 580f606c848SSatoshi Asami struct shlib_list *shp; 581b9ae52e3SPaul Richards int i; 582b9ae52e3SPaul Richards 5837c6da7dcSJohn Polstra if ((fd = open(hints_file, O_RDONLY, 0)) == -1) { 5847c6da7dcSJohn Polstra warn("%s", hints_file); 585b9ae52e3SPaul Richards return -1; 586b9ae52e3SPaul Richards } 587b9ae52e3SPaul Richards 58880c71499SPeter Wemm msize = PAGE_SIZE; 58961f9ce8dSNate Williams addr = mmap(0, msize, PROT_READ, MAP_COPY, fd, 0); 590b9ae52e3SPaul Richards 591614d19caSJohn Polstra if (addr == MAP_FAILED) { 5927c6da7dcSJohn Polstra warn("%s", hints_file); 593b9ae52e3SPaul Richards return -1; 594b9ae52e3SPaul Richards } 595b9ae52e3SPaul Richards 596b9ae52e3SPaul Richards hdr = (struct hints_header *)addr; 597b9ae52e3SPaul Richards if (HH_BADMAG(*hdr)) { 598ab845347SBruce Evans warnx("%s: bad magic: %lo", hints_file, 599ab845347SBruce Evans (unsigned long)hdr->hh_magic); 600b9ae52e3SPaul Richards return -1; 601b9ae52e3SPaul Richards } 602b9ae52e3SPaul Richards 60380c71499SPeter Wemm if (hdr->hh_version != LD_HINTS_VERSION_1 && 60480c71499SPeter Wemm hdr->hh_version != LD_HINTS_VERSION_2) { 605ab845347SBruce Evans warnx("unsupported version: %ld", (long)hdr->hh_version); 606b9ae52e3SPaul Richards return -1; 607b9ae52e3SPaul Richards } 608b9ae52e3SPaul Richards 609b9ae52e3SPaul Richards if (hdr->hh_ehints > msize) { 610614d19caSJohn Polstra fsize = hdr->hh_ehints; 611614d19caSJohn Polstra munmap(addr, msize); 612614d19caSJohn Polstra addr = mmap(0, fsize, PROT_READ, MAP_COPY, fd, 0); 613614d19caSJohn Polstra if (addr == MAP_FAILED) { 6147c6da7dcSJohn Polstra warn("%s", hints_file); 615b9ae52e3SPaul Richards return -1; 616b9ae52e3SPaul Richards } 617614d19caSJohn Polstra hdr = (struct hints_header *)addr; 618b9ae52e3SPaul Richards } 619b9ae52e3SPaul Richards close(fd); 620b9ae52e3SPaul Richards 621b9ae52e3SPaul Richards blist = (struct hints_bucket *)(addr + hdr->hh_hashtab); 622b9ae52e3SPaul Richards strtab = (char *)(addr + hdr->hh_strtab); 623b9ae52e3SPaul Richards 624d4ba5766SPeter Wemm if (hdr->hh_version >= LD_HINTS_VERSION_2) 625d4ba5766SPeter Wemm add_search_path(strtab + hdr->hh_dirlist); 626d4ba5766SPeter Wemm else if (rescan) 627d4ba5766SPeter Wemm errx(1, "%s too old and does not contain the search path", 628d4ba5766SPeter Wemm hints_file); 629d4ba5766SPeter Wemm 630d4ba5766SPeter Wemm if (rescan) 631d4ba5766SPeter Wemm return 0; 632d4ba5766SPeter Wemm 633b9ae52e3SPaul Richards for (i = 0; i < hdr->hh_nbucket; i++) { 634b9ae52e3SPaul Richards struct hints_bucket *bp = &blist[i]; 635b9ae52e3SPaul Richards 636b9ae52e3SPaul Richards /* Sanity check */ 637b9ae52e3SPaul Richards if (bp->hi_namex >= hdr->hh_strtab_sz) { 638b50d7faeSPhilippe Charnier warnx("bad name index: %#x", bp->hi_namex); 639b9ae52e3SPaul Richards return -1; 640b9ae52e3SPaul Richards } 641b9ae52e3SPaul Richards if (bp->hi_pathx >= hdr->hh_strtab_sz) { 642b50d7faeSPhilippe Charnier warnx("bad path index: %#x", bp->hi_pathx); 643b9ae52e3SPaul Richards return -1; 644b9ae52e3SPaul Richards } 645b9ae52e3SPaul Richards 646f606c848SSatoshi Asami /* Allocate new list element */ 647f606c848SSatoshi Asami shp = (struct shlib_list *)xmalloc(sizeof *shp); 648f606c848SSatoshi Asami shp->name = strdup(strtab + bp->hi_namex); 649f606c848SSatoshi Asami shp->path = strdup(strtab + bp->hi_pathx); 650f606c848SSatoshi Asami bcopy(bp->hi_dewey, shp->dewey, sizeof(shp->dewey)); 651f606c848SSatoshi Asami shp->ndewey = bp->hi_ndewey; 652f606c848SSatoshi Asami shp->next = NULL; 653f606c848SSatoshi Asami 654f606c848SSatoshi Asami *shlib_tail = shp; 655f606c848SSatoshi Asami shlib_tail = &shp->next; 656b9ae52e3SPaul Richards } 657b9ae52e3SPaul Richards 658b9ae52e3SPaul Richards return 0; 659b9ae52e3SPaul Richards } 660b9ae52e3SPaul Richards 661f606c848SSatoshi Asami static void 662f606c848SSatoshi Asami listhints() 663f606c848SSatoshi Asami { 664f606c848SSatoshi Asami struct shlib_list *shp; 665f606c848SSatoshi Asami int i; 666f606c848SSatoshi Asami 6677c6da7dcSJohn Polstra printf("%s:\n", hints_file); 66880c71499SPeter Wemm printf("\tsearch directories: %s\n", dir_list); 669f606c848SSatoshi Asami 670f606c848SSatoshi Asami for (i = 0, shp = shlib_head; shp; i++, shp = shp->next) 671f606c848SSatoshi Asami printf("\t%d:-l%s.%d.%d => %s\n", 672f606c848SSatoshi Asami i, shp->name, shp->major, shp->minor, shp->path); 673f606c848SSatoshi Asami 674f606c848SSatoshi Asami return; 675f606c848SSatoshi Asami } 676