17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 55aefb655Srie * Common Development and Distribution License (the "License"). 65aefb655Srie * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 215aefb655Srie 227c478bd9Sstevel@tonic-gate /* 237257d1b4Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 245aefb655Srie * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267257d1b4Sraf 277c478bd9Sstevel@tonic-gate /* 287c478bd9Sstevel@tonic-gate * 4.x ld.so directory caching: run-time link-editor specific functions. 297c478bd9Sstevel@tonic-gate */ 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #include <dirent.h> 327c478bd9Sstevel@tonic-gate #include <string.h> 337c478bd9Sstevel@tonic-gate #include <sys/stat.h> 347c478bd9Sstevel@tonic-gate #include <fcntl.h> 357c478bd9Sstevel@tonic-gate #include <unistd.h> 367c478bd9Sstevel@tonic-gate #include "_a.out.h" 377c478bd9Sstevel@tonic-gate #include "cache_a.out.h" 387c478bd9Sstevel@tonic-gate #include "_rtld.h" 397c478bd9Sstevel@tonic-gate #include "msg.h" 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate static int stol(); 427c478bd9Sstevel@tonic-gate static int rest_ok(); 437c478bd9Sstevel@tonic-gate static int verscmp(); 447c478bd9Sstevel@tonic-gate static void fix_lo(); 457c478bd9Sstevel@tonic-gate static int extract_name(); 467c478bd9Sstevel@tonic-gate static int hash(); 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate static struct link_object *get_lo(); 497c478bd9Sstevel@tonic-gate static struct dbd *new_dbd(); 507c478bd9Sstevel@tonic-gate static struct db *find_so(); 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate #define SKIP_DOT(str) ((*str == '.') ? ++str : str) 537c478bd9Sstevel@tonic-gate #define EMPTY(str) ((str == NULL) || (*str == '\0')) 547c478bd9Sstevel@tonic-gate #define isdigit(c) (((c) >= '0') && ((c) <= '9') ? 1:0) 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate static struct dbd *dbd_head = NULL; /* head of data bases */ 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate /* 607c478bd9Sstevel@tonic-gate * Given a db - find the highest shared versioned object. The 617c478bd9Sstevel@tonic-gate * highest versioned object is the .so with a matching major number 627c478bd9Sstevel@tonic-gate * but the highest minor number 637c478bd9Sstevel@tonic-gate */ 647c478bd9Sstevel@tonic-gate char * 657c478bd9Sstevel@tonic-gate ask_db(dbp, file) 667c478bd9Sstevel@tonic-gate struct db *dbp; 677c478bd9Sstevel@tonic-gate const char *file; 687c478bd9Sstevel@tonic-gate { 697c478bd9Sstevel@tonic-gate char *libname, *n; 707c478bd9Sstevel@tonic-gate char *mnp; 717c478bd9Sstevel@tonic-gate char *mjp; 727c478bd9Sstevel@tonic-gate int liblen; 737c478bd9Sstevel@tonic-gate int major = 0; 747c478bd9Sstevel@tonic-gate int to_min; 757c478bd9Sstevel@tonic-gate struct dbe *ep; 767c478bd9Sstevel@tonic-gate struct link_object *tlop; 777c478bd9Sstevel@tonic-gate int index; 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate n = (char *)file; 807c478bd9Sstevel@tonic-gate if ((liblen = extract_name(&n)) == -1) 817c478bd9Sstevel@tonic-gate return (NULL); 827c478bd9Sstevel@tonic-gate if ((libname = malloc(liblen + 1)) == 0) 837c478bd9Sstevel@tonic-gate return (NULL); 847c478bd9Sstevel@tonic-gate (void) strncpy(libname, n, liblen); 857c478bd9Sstevel@tonic-gate libname[liblen] = NULL; 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate if (strncmp(MSG_ORIG(MSG_FIL_DOTSODOT), (n + liblen), 887c478bd9Sstevel@tonic-gate MSG_FIL_DOTSODOT_SIZE)) 897c478bd9Sstevel@tonic-gate return (NULL); 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate mnp = mjp = ((char *)file + MSG_FIL_LIB_SIZE + liblen + 927c478bd9Sstevel@tonic-gate MSG_FIL_DOTSODOT_SIZE); 937c478bd9Sstevel@tonic-gate if (!(stol(mjp, '.', &mnp, &major) && (*mnp == '.') && 947c478bd9Sstevel@tonic-gate rest_ok(mnp + 1))) 957c478bd9Sstevel@tonic-gate return (NULL); 967c478bd9Sstevel@tonic-gate to_min = mnp - file + 1; 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate /* 997c478bd9Sstevel@tonic-gate * Search appropriate hash bucket for a matching entry. 1007c478bd9Sstevel@tonic-gate */ 1017c478bd9Sstevel@tonic-gate index = hash(libname, liblen, major); 1027c478bd9Sstevel@tonic-gate for (ep = (struct dbe *)&(dbp->db_hash[index]); (ep && ep->dbe_lop); 1037c478bd9Sstevel@tonic-gate ep = ep->dbe_next == 0 ? NULL : 1047c478bd9Sstevel@tonic-gate /* LINTED */ 1057c478bd9Sstevel@tonic-gate (struct dbe *)&AP(dbp)[ep->dbe_next]) { 1067c478bd9Sstevel@tonic-gate /* LINTED */ 1077c478bd9Sstevel@tonic-gate tlop = (struct link_object *)&AP(dbp)[ep->dbe_lop]; 1087c478bd9Sstevel@tonic-gate if (tlop->lo_major == major) 1097c478bd9Sstevel@tonic-gate if (strcmp((char *)&AP(dbp)[tlop->lo_name], 1107c478bd9Sstevel@tonic-gate libname) == 0) 1117c478bd9Sstevel@tonic-gate break; 1127c478bd9Sstevel@tonic-gate } 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate /* 1157c478bd9Sstevel@tonic-gate * If no entry was found, we've lost. 1167c478bd9Sstevel@tonic-gate */ 1177c478bd9Sstevel@tonic-gate if (!(ep && ep->dbe_lop)) 1187c478bd9Sstevel@tonic-gate return (NULL); 1197c478bd9Sstevel@tonic-gate if (verscmp(file + to_min, 1207c478bd9Sstevel@tonic-gate &AP(dbp)[ep->dbe_name] + tlop->lo_minor) > 0) 1215aefb655Srie eprintf(&lml_main, ERR_WARNING, MSG_INTL(MSG_GEN_OLDREV), 1227c478bd9Sstevel@tonic-gate &AP(dbp)[ep->dbe_name], file + to_min); 1237c478bd9Sstevel@tonic-gate return (&AP(dbp)[ep->dbe_name]); 1247c478bd9Sstevel@tonic-gate } 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate /* 1277c478bd9Sstevel@tonic-gate * Given a directory name - give back a data base. The data base may have 1287c478bd9Sstevel@tonic-gate * orginated from the mmapped file or temporarily created 1297c478bd9Sstevel@tonic-gate */ 1307c478bd9Sstevel@tonic-gate struct db * 1317c478bd9Sstevel@tonic-gate lo_cache(const char *ds) 1327c478bd9Sstevel@tonic-gate { 1337c478bd9Sstevel@tonic-gate struct db *dbp; /* database pointer */ 1347c478bd9Sstevel@tonic-gate struct dbd *dbdp; /* working database descriptor */ 1357c478bd9Sstevel@tonic-gate struct dbd **dbdpp; /* insertion pointer */ 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate dbdpp = &dbd_head; 1387c478bd9Sstevel@tonic-gate for (dbdp = dbd_head; dbdp; dbdp = dbdp->dbd_next) { 1397c478bd9Sstevel@tonic-gate if (strcmp(ds, &AP(dbdp->dbd_db)[dbdp->dbd_db->db_name]) == 0) 1407c478bd9Sstevel@tonic-gate return (dbdp->dbd_db); 1417c478bd9Sstevel@tonic-gate dbdpp = &dbdp->dbd_next; 1427c478bd9Sstevel@tonic-gate } 1437c478bd9Sstevel@tonic-gate if (dbp = find_so(ds)) { 1447c478bd9Sstevel@tonic-gate (void) new_dbd(dbdpp, dbp); 1457c478bd9Sstevel@tonic-gate } 1467c478bd9Sstevel@tonic-gate return (dbp); 1477c478bd9Sstevel@tonic-gate } 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate /* 1507c478bd9Sstevel@tonic-gate * Build a database for the directory "ds". 1517c478bd9Sstevel@tonic-gate */ 1527c478bd9Sstevel@tonic-gate static struct db * 1537c478bd9Sstevel@tonic-gate find_so(const char *ds) 1547c478bd9Sstevel@tonic-gate { 1557c478bd9Sstevel@tonic-gate int fd; /* descriptor on directory */ 1567c478bd9Sstevel@tonic-gate int n; /* bytes from getdents */ 1577c478bd9Sstevel@tonic-gate char *cp; /* working char * */ 158*cb511613SAli Bahrami rtld_stat_t sb; /* buffer for stat'ing directory */ 1597c478bd9Sstevel@tonic-gate struct db *dbp; /* database */ 1607c478bd9Sstevel@tonic-gate static caddr_t buf = NULL; /* buffer for doing getdents */ 1617c478bd9Sstevel@tonic-gate static long bs; /* cached blocksize for getdents */ 1627c478bd9Sstevel@tonic-gate struct link_object *tlop; /* working link object ptr. */ 1637c478bd9Sstevel@tonic-gate struct dirent *dp; /* directory entry ptr. */ 1647c478bd9Sstevel@tonic-gate struct dbe *ep; /* working db_entry ptr. */ 1657c478bd9Sstevel@tonic-gate char *mnp; /* where minor version begins */ 1667c478bd9Sstevel@tonic-gate char *mjp; /* where major version begins */ 1677c478bd9Sstevel@tonic-gate int m; /* the major number */ 1687c478bd9Sstevel@tonic-gate int to_min; /* index into string of minor */ 1697c478bd9Sstevel@tonic-gate int cplen; /* length of X */ 1707c478bd9Sstevel@tonic-gate int index; /* the hash value */ 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate /* 1737c478bd9Sstevel@tonic-gate * Try to open directory. Failing that, just return silently. 1747c478bd9Sstevel@tonic-gate */ 1757c478bd9Sstevel@tonic-gate if ((fd = open(ds, O_RDONLY)) == -1) 1767c478bd9Sstevel@tonic-gate return ((struct db *)NULL); 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate /* 1797c478bd9Sstevel@tonic-gate * If we have not yet gotten a buffer for reading directories, 1807c478bd9Sstevel@tonic-gate * allocate it now. Size it according to the most efficient size 1817c478bd9Sstevel@tonic-gate * for the first directory we open successfully. 1827c478bd9Sstevel@tonic-gate */ 1837c478bd9Sstevel@tonic-gate if (!buf) { 184*cb511613SAli Bahrami if (rtld_fstat(fd, &sb) == -1) { 1857c478bd9Sstevel@tonic-gate (void) close(fd); 1867c478bd9Sstevel@tonic-gate return ((struct db *)NULL); 1877c478bd9Sstevel@tonic-gate } 1887c478bd9Sstevel@tonic-gate bs = sb.st_blksize; 1897c478bd9Sstevel@tonic-gate buf = calloc(bs, 1); 1907c478bd9Sstevel@tonic-gate } 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate /* 1937c478bd9Sstevel@tonic-gate * Have a directory, have a buffer. Allocate up a database 1947c478bd9Sstevel@tonic-gate * and initialize it. 1957c478bd9Sstevel@tonic-gate */ 1967c478bd9Sstevel@tonic-gate dbp = calloc(sizeof (struct db), 1); 1977c478bd9Sstevel@tonic-gate dbp->db_name = RELPTR(dbp, calloc((strlen(ds) + 1), 1)); 1987c478bd9Sstevel@tonic-gate (void) strcpy((char *)&AP(dbp)[dbp->db_name], ds); 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate /* 2017c478bd9Sstevel@tonic-gate * Scan the directory looking for shared libraries. getdents() 2027c478bd9Sstevel@tonic-gate * failures are silently ignored and terminate the scan. 2037c478bd9Sstevel@tonic-gate */ 2047c478bd9Sstevel@tonic-gate /* LINTED */ 2057c478bd9Sstevel@tonic-gate while ((n = getdents(fd, (struct dirent *)buf, bs)) > 0) 2067c478bd9Sstevel@tonic-gate /* LINTED */ 2077c478bd9Sstevel@tonic-gate for (dp = (struct dirent *)buf; 2087c478bd9Sstevel@tonic-gate /* LINTED */ 2097c478bd9Sstevel@tonic-gate dp && (dp < (struct dirent *)(buf + n)); 2107c478bd9Sstevel@tonic-gate /* LINTED */ 2117c478bd9Sstevel@tonic-gate dp = (struct dirent *)((dp->d_reclen == 0) ? 2127c478bd9Sstevel@tonic-gate NULL : (char *)dp + dp->d_reclen)) { 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate /* 2157c478bd9Sstevel@tonic-gate * If file starts with a "lib", then extract the X 2167c478bd9Sstevel@tonic-gate * from libX. 2177c478bd9Sstevel@tonic-gate */ 2187c478bd9Sstevel@tonic-gate cp = dp->d_name; 2197c478bd9Sstevel@tonic-gate if ((cplen = extract_name(&cp)) == -1) 2207c478bd9Sstevel@tonic-gate continue; 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate /* 2237c478bd9Sstevel@tonic-gate * Is the next component ".so."? 2247c478bd9Sstevel@tonic-gate */ 2257c478bd9Sstevel@tonic-gate if (strncmp(MSG_ORIG(MSG_FIL_DOTSODOT), (cp + cplen), 2267c478bd9Sstevel@tonic-gate MSG_FIL_DOTSODOT_SIZE)) 2277c478bd9Sstevel@tonic-gate continue; 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate /* 2307c478bd9Sstevel@tonic-gate * Check if next component is the major number and 2317c478bd9Sstevel@tonic-gate * whether following components are legal. 2327c478bd9Sstevel@tonic-gate */ 2337c478bd9Sstevel@tonic-gate mnp = mjp = (dp->d_name + MSG_FIL_LIB_SIZE + cplen + 2347c478bd9Sstevel@tonic-gate MSG_FIL_DOTSODOT_SIZE); 2357c478bd9Sstevel@tonic-gate if (!(stol(mjp, '.', &mnp, &m) && (*mnp == '.') && 2367c478bd9Sstevel@tonic-gate rest_ok(mnp + 1))) 2377c478bd9Sstevel@tonic-gate continue; 2387c478bd9Sstevel@tonic-gate to_min = mnp - dp->d_name + 1; 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate /* 2417c478bd9Sstevel@tonic-gate * Have libX.so.major.minor - attempt to add it to the 2427c478bd9Sstevel@tonic-gate * cache. If there is another with the same major 2437c478bd9Sstevel@tonic-gate * number then the chose the object with the highest 2447c478bd9Sstevel@tonic-gate * minor number 2457c478bd9Sstevel@tonic-gate */ 2467c478bd9Sstevel@tonic-gate index = hash(cp, cplen, m); 2477c478bd9Sstevel@tonic-gate ep = &(dbp->db_hash[index]); 2487c478bd9Sstevel@tonic-gate if (ep->dbe_lop == NULL) { 2497c478bd9Sstevel@tonic-gate ep->dbe_lop = (long)get_lo(dbp, cp, 2507c478bd9Sstevel@tonic-gate cplen, m, to_min); 2517c478bd9Sstevel@tonic-gate /* LINTED */ 2527c478bd9Sstevel@tonic-gate tlop = (struct link_object *) 2537c478bd9Sstevel@tonic-gate &AP(dbp)[ep->dbe_lop]; 2547c478bd9Sstevel@tonic-gate (void) strcpy(&AP(dbp)[tlop->lo_next], 2557c478bd9Sstevel@tonic-gate dp->d_name); 2567c478bd9Sstevel@tonic-gate continue; 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate for (ep = &(dbp->db_hash[index]); ep; 2597c478bd9Sstevel@tonic-gate /* LINTED */ 2607c478bd9Sstevel@tonic-gate ep = (struct dbe *)&AP(dbp)[ep->dbe_next]) { 2617c478bd9Sstevel@tonic-gate /* LINTED */ 2627c478bd9Sstevel@tonic-gate tlop = (struct link_object *) 2637c478bd9Sstevel@tonic-gate &AP(dbp)[ep->dbe_lop]; 2647c478bd9Sstevel@tonic-gate 2657c478bd9Sstevel@tonic-gate /* 2667c478bd9Sstevel@tonic-gate * Choose the highest minor version 2677c478bd9Sstevel@tonic-gate */ 2687c478bd9Sstevel@tonic-gate if ((tlop->lo_major == m) && 2697c478bd9Sstevel@tonic-gate (strncmp(&AP(dbp)[tlop->lo_name], 2707c478bd9Sstevel@tonic-gate cp, cplen) == 0) && 2717c478bd9Sstevel@tonic-gate (*(&AP(dbp)[tlop->lo_name + 2727c478bd9Sstevel@tonic-gate cplen]) == '\0')) { 2737c478bd9Sstevel@tonic-gate if (verscmp(dp->d_name + to_min, 2747c478bd9Sstevel@tonic-gate (char *)(&AP(dbp)[tlop->lo_next] 2757c478bd9Sstevel@tonic-gate + to_min)) > 0) 2767c478bd9Sstevel@tonic-gate (void) strcpy(&AP(dbp) 2777c478bd9Sstevel@tonic-gate [tlop->lo_next], 2787c478bd9Sstevel@tonic-gate dp->d_name); 2797c478bd9Sstevel@tonic-gate break; 2807c478bd9Sstevel@tonic-gate } 2817c478bd9Sstevel@tonic-gate if (ep->dbe_next == NULL) { 2827c478bd9Sstevel@tonic-gate ep->dbe_next = RELPTR(dbp, 2837c478bd9Sstevel@tonic-gate calloc(sizeof (struct dbe), 1)); 2847c478bd9Sstevel@tonic-gate /* LINTED */ 2857c478bd9Sstevel@tonic-gate ep = (struct dbe *) 2867c478bd9Sstevel@tonic-gate &AP(dbp)[ep->dbe_next]; 2877c478bd9Sstevel@tonic-gate ep->dbe_lop = (long)get_lo(dbp, 2887c478bd9Sstevel@tonic-gate cp, cplen, m, to_min); 2897c478bd9Sstevel@tonic-gate /* LINTED */ 2907c478bd9Sstevel@tonic-gate tlop = (struct link_object *) 2917c478bd9Sstevel@tonic-gate &AP(dbp)[ep->dbe_lop]; 2927c478bd9Sstevel@tonic-gate (void) strcpy(&AP(dbp)[tlop->lo_next], 2937c478bd9Sstevel@tonic-gate dp->d_name); 2947c478bd9Sstevel@tonic-gate break; 2957c478bd9Sstevel@tonic-gate } 2967c478bd9Sstevel@tonic-gate } 2977c478bd9Sstevel@tonic-gate } 2987c478bd9Sstevel@tonic-gate fix_lo(dbp); 2997c478bd9Sstevel@tonic-gate (void) close(fd); 3007c478bd9Sstevel@tonic-gate return (dbp); 3017c478bd9Sstevel@tonic-gate } 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate /* 3047c478bd9Sstevel@tonic-gate * Allocate and fill in the fields for a link_object 3057c478bd9Sstevel@tonic-gate */ 3067c478bd9Sstevel@tonic-gate static struct link_object * 3077c478bd9Sstevel@tonic-gate get_lo(dbp, cp, cplen, m, n) 3087c478bd9Sstevel@tonic-gate struct db *dbp; /* data base */ 3097c478bd9Sstevel@tonic-gate char *cp; /* ptr. to X of libX */ 3107c478bd9Sstevel@tonic-gate int cplen; /* length of X */ 3117c478bd9Sstevel@tonic-gate int m; /* major version */ 3127c478bd9Sstevel@tonic-gate int n; /* index to minor version */ 3137c478bd9Sstevel@tonic-gate { 3147c478bd9Sstevel@tonic-gate struct link_object *lop; /* link_object to be returned */ 3157c478bd9Sstevel@tonic-gate struct link_object *tlop; /* working copy of the above */ 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate /* 3187c478bd9Sstevel@tonic-gate * Allocate a link object prototype in the database heap. 3197c478bd9Sstevel@tonic-gate * Store the numeric major (interface) number, but the minor 3207c478bd9Sstevel@tonic-gate * number is stored in the database as an index to the string 3217c478bd9Sstevel@tonic-gate * representing the minor version. By keeping the minor version 3227c478bd9Sstevel@tonic-gate * as a string, "subfields" (i.e., major.minor[.other.fields. etc.]) 3237c478bd9Sstevel@tonic-gate * are permitted. Although not meaningful to the link editor, this 3247c478bd9Sstevel@tonic-gate * permits run-time substitution of arbitrary customer revisions, 3257c478bd9Sstevel@tonic-gate * although introducing the confusion of overloading the lo_minor 3267c478bd9Sstevel@tonic-gate * field in the database (!) 3277c478bd9Sstevel@tonic-gate */ 3287c478bd9Sstevel@tonic-gate lop = (struct link_object *)RELPTR(dbp, 3297c478bd9Sstevel@tonic-gate calloc(sizeof (struct link_object), 1)); 3307c478bd9Sstevel@tonic-gate /* LINTED */ 3317c478bd9Sstevel@tonic-gate tlop = (struct link_object *)&AP(dbp)[(long)lop]; 3327c478bd9Sstevel@tonic-gate tlop->lo_major = m; 3337c478bd9Sstevel@tonic-gate tlop->lo_minor = n; 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate /* 3367c478bd9Sstevel@tonic-gate * Allocate space for the complete path name on the host program's 3377c478bd9Sstevel@tonic-gate * heap -- as we have to save it from the directory buffer which 3387c478bd9Sstevel@tonic-gate * might otherwise get re-used on us. Note that this space 3397c478bd9Sstevel@tonic-gate * is wasted -- we can not assume that it can be reclaimed. 3407c478bd9Sstevel@tonic-gate */ 3417c478bd9Sstevel@tonic-gate tlop->lo_next = (long)RELPTR(dbp, calloc(MAXNAMLEN, 1)); 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate /* 3447c478bd9Sstevel@tonic-gate * Store the prototype name in the link object in the database. 3457c478bd9Sstevel@tonic-gate */ 3467c478bd9Sstevel@tonic-gate tlop->lo_name = (long)RELPTR(dbp, calloc((cplen + 1), 1)); 3477c478bd9Sstevel@tonic-gate (void) strncpy((char *)&AP(dbp)[tlop->lo_name], cp, cplen); 3487c478bd9Sstevel@tonic-gate return (lop); 3497c478bd9Sstevel@tonic-gate } 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate /* 3527c478bd9Sstevel@tonic-gate * Pull the "X" from libX, set name to X and return the 3537c478bd9Sstevel@tonic-gate * length of X 3547c478bd9Sstevel@tonic-gate */ 3557c478bd9Sstevel@tonic-gate static int 3567c478bd9Sstevel@tonic-gate extract_name(name) 3577c478bd9Sstevel@tonic-gate char **name; 3587c478bd9Sstevel@tonic-gate { 3597c478bd9Sstevel@tonic-gate char *ls; /* string after LIB root */ 3607c478bd9Sstevel@tonic-gate char *dp; /* string before first delimiter */ 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate if (strncmp(*name, MSG_ORIG(MSG_FIL_LIB), MSG_FIL_LIB_SIZE) == 0) { 3637c478bd9Sstevel@tonic-gate ls = *name + MSG_FIL_LIB_SIZE; 3647c478bd9Sstevel@tonic-gate if ((dp = (char *)strchr(ls, '.')) != (char *)0) { 3657c478bd9Sstevel@tonic-gate *name = ls; 3667c478bd9Sstevel@tonic-gate return (dp - ls); 3677c478bd9Sstevel@tonic-gate } 3687c478bd9Sstevel@tonic-gate } 3697c478bd9Sstevel@tonic-gate return (-1); 3707c478bd9Sstevel@tonic-gate } 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate /* 3737c478bd9Sstevel@tonic-gate * Make a pass through the data base to set the dbe_name of a dbe. This 3747c478bd9Sstevel@tonic-gate * is necessary because there may be several revisions of a library 3757c478bd9Sstevel@tonic-gate * but only one will be chosen. 3767c478bd9Sstevel@tonic-gate */ 3777c478bd9Sstevel@tonic-gate static void 3787c478bd9Sstevel@tonic-gate fix_lo(dbp) 3797c478bd9Sstevel@tonic-gate struct db *dbp; 3807c478bd9Sstevel@tonic-gate { 3817c478bd9Sstevel@tonic-gate int i; /* loop temporary */ 3827c478bd9Sstevel@tonic-gate int dirlen = strlen(&AP(dbp)[dbp->db_name]); 3837c478bd9Sstevel@tonic-gate /* length of directory pathname */ 3847c478bd9Sstevel@tonic-gate char *cp; /* working temporary */ 3857c478bd9Sstevel@tonic-gate char *tp; /* working temporary */ 3867c478bd9Sstevel@tonic-gate struct dbe *ep; /* working copy of dbe */ 3877c478bd9Sstevel@tonic-gate struct link_object *lop; /* working copy of link_object */ 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate for (i = 0; i < DB_HASH; i++) { 3907c478bd9Sstevel@tonic-gate for (ep = &(dbp->db_hash[i]); ep && ep->dbe_lop; 3917c478bd9Sstevel@tonic-gate (ep = ep->dbe_next == 0 ? NULL : 3927c478bd9Sstevel@tonic-gate /* LINTED */ 3937c478bd9Sstevel@tonic-gate (struct dbe *)&AP(dbp)[ep->dbe_next])) { 3947c478bd9Sstevel@tonic-gate /* LINTED */ 3957c478bd9Sstevel@tonic-gate lop = (struct link_object *)&AP(dbp)[ep->dbe_lop]; 3967c478bd9Sstevel@tonic-gate tp = &AP(dbp)[lop->lo_next]; 3977c478bd9Sstevel@tonic-gate ep->dbe_name = RELPTR(dbp, 3987c478bd9Sstevel@tonic-gate calloc((dirlen + strlen(tp) + 2), 1)); 3997c478bd9Sstevel@tonic-gate lop->lo_minor += dirlen + 1; 4007c478bd9Sstevel@tonic-gate cp = strncpy(&AP(dbp)[ep->dbe_name], 4017c478bd9Sstevel@tonic-gate &AP(dbp)[dbp->db_name], dirlen); 4027c478bd9Sstevel@tonic-gate cp = strncpy(cp + dirlen, MSG_ORIG(MSG_STR_SLASH), 4037c478bd9Sstevel@tonic-gate MSG_STR_SLASH_SIZE); 4047c478bd9Sstevel@tonic-gate (void) strcpy(cp + 1, tp); 4057c478bd9Sstevel@tonic-gate } 4067c478bd9Sstevel@tonic-gate } 4077c478bd9Sstevel@tonic-gate } 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate /* 4107c478bd9Sstevel@tonic-gate * Allocate a new dbd, append it after dbdpp and set the dbd_dbp to dbp. 4117c478bd9Sstevel@tonic-gate */ 4127c478bd9Sstevel@tonic-gate static struct dbd * 4137c478bd9Sstevel@tonic-gate new_dbd(dbdpp, dbp) 4147c478bd9Sstevel@tonic-gate struct dbd **dbdpp; /* insertion point */ 4157c478bd9Sstevel@tonic-gate struct db *dbp; /* db associated with this dbd */ 4167c478bd9Sstevel@tonic-gate { 4177c478bd9Sstevel@tonic-gate struct dbd *dbdp; /* working dbd ptr. */ 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate dbdp = malloc(sizeof (struct dbd)); 4207c478bd9Sstevel@tonic-gate dbdp->dbd_db = dbp; 4217c478bd9Sstevel@tonic-gate dbdp->dbd_next = NULL; 4227c478bd9Sstevel@tonic-gate *dbdpp = dbdp; 4237c478bd9Sstevel@tonic-gate return (dbdp); 4247c478bd9Sstevel@tonic-gate } 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate /* 4277c478bd9Sstevel@tonic-gate * Calculate hash index for link object. 4287c478bd9Sstevel@tonic-gate * This is based on X.major from libX.so.major.minor. 4297c478bd9Sstevel@tonic-gate */ 4307c478bd9Sstevel@tonic-gate static int 4317c478bd9Sstevel@tonic-gate hash(np, nchrs, m) 4327c478bd9Sstevel@tonic-gate char *np; /* X of libX */ 4337c478bd9Sstevel@tonic-gate int nchrs; /* no of chrs. to hash on */ 4347c478bd9Sstevel@tonic-gate int m; /* the major version */ 4357c478bd9Sstevel@tonic-gate { 4367c478bd9Sstevel@tonic-gate int h; /* for loop counter */ 4377c478bd9Sstevel@tonic-gate char *cp; /* working (char *) ptr */ 4387c478bd9Sstevel@tonic-gate 4397c478bd9Sstevel@tonic-gate for (h = 0, cp = np; h < nchrs; h++, cp++) 4407c478bd9Sstevel@tonic-gate h = (h << 1) + *cp; 4417c478bd9Sstevel@tonic-gate h += (h << 1) + m; 4427c478bd9Sstevel@tonic-gate h = ((h & 0x7fffffff) % DB_HASH); 4437c478bd9Sstevel@tonic-gate return (h); 4447c478bd9Sstevel@tonic-gate } 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate /* 4477c478bd9Sstevel@tonic-gate * Test whether the string is of digit[.digit]* format 4487c478bd9Sstevel@tonic-gate */ 4497c478bd9Sstevel@tonic-gate static int 4507c478bd9Sstevel@tonic-gate rest_ok(str) 4517c478bd9Sstevel@tonic-gate char *str; /* input string */ 4527c478bd9Sstevel@tonic-gate { 4537c478bd9Sstevel@tonic-gate int dummy; /* integer place holder */ 4547c478bd9Sstevel@tonic-gate int legal = 1; /* return flag */ 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate while (!EMPTY(str)) { 4577c478bd9Sstevel@tonic-gate if (!stol(str, '.', &str, &dummy)) { 4587c478bd9Sstevel@tonic-gate legal = 0; 4597c478bd9Sstevel@tonic-gate break; 4607c478bd9Sstevel@tonic-gate } 4617c478bd9Sstevel@tonic-gate if (EMPTY(str)) 4627c478bd9Sstevel@tonic-gate break; 4637c478bd9Sstevel@tonic-gate else 4647c478bd9Sstevel@tonic-gate /* LINTED */ 4657c478bd9Sstevel@tonic-gate (SKIP_DOT(str)); 4667c478bd9Sstevel@tonic-gate } 4677c478bd9Sstevel@tonic-gate return (legal); 4687c478bd9Sstevel@tonic-gate } 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate /* 4717c478bd9Sstevel@tonic-gate * Compare 2 strings and test whether they are of the form digit[.digit]*. 4727c478bd9Sstevel@tonic-gate * It will return -1, 0, or 1 depending on whether c1p is less, equal or 4737c478bd9Sstevel@tonic-gate * greater than c2p 4747c478bd9Sstevel@tonic-gate */ 4757c478bd9Sstevel@tonic-gate static int 4767c478bd9Sstevel@tonic-gate verscmp(const char *c1p, const char *c2p) 4777c478bd9Sstevel@tonic-gate { 4787c478bd9Sstevel@tonic-gate char *l_c1p = (char *)c1p; /* working copy of c1p */ 4797c478bd9Sstevel@tonic-gate char *l_c2p = (char *)c2p; /* working copy of c2p */ 4807c478bd9Sstevel@tonic-gate int l_c1p_ok = 0; /* is c1p a legal string */ 4817c478bd9Sstevel@tonic-gate int c2p_dig = 0; /* int that c1p currently */ 4827c478bd9Sstevel@tonic-gate /* represents */ 4837c478bd9Sstevel@tonic-gate int c1p_dig = 0; /* int that c2p currently */ 4847c478bd9Sstevel@tonic-gate /* represents */ 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate while (((l_c1p_ok = stol(l_c1p, '.', &l_c1p, &c1p_dig)) == 1) && 4877c478bd9Sstevel@tonic-gate stol(l_c2p, '.', &l_c2p, &c2p_dig) && (c2p_dig == c1p_dig)) { 4887c478bd9Sstevel@tonic-gate if (EMPTY(l_c1p) && EMPTY(l_c2p)) 4897c478bd9Sstevel@tonic-gate return (0); 4907c478bd9Sstevel@tonic-gate else if (EMPTY(l_c1p) && !EMPTY(l_c2p) && 4917c478bd9Sstevel@tonic-gate rest_ok(SKIP_DOT(l_c2p))) 4927c478bd9Sstevel@tonic-gate return (-1); 4937c478bd9Sstevel@tonic-gate else if (EMPTY(l_c2p) && !EMPTY(l_c1p) && 4947c478bd9Sstevel@tonic-gate rest_ok(SKIP_DOT(l_c1p))) 4957c478bd9Sstevel@tonic-gate return (1); 4967c478bd9Sstevel@tonic-gate l_c1p++; l_c2p++; 4977c478bd9Sstevel@tonic-gate }; 4987c478bd9Sstevel@tonic-gate if (!l_c1p_ok) 4997c478bd9Sstevel@tonic-gate return (-1); 5007c478bd9Sstevel@tonic-gate else if (c1p_dig < c2p_dig) 5017c478bd9Sstevel@tonic-gate return (-1); 5027c478bd9Sstevel@tonic-gate else if ((c1p_dig > c2p_dig) && rest_ok(SKIP_DOT(l_c1p))) 5037c478bd9Sstevel@tonic-gate return (1); 5047c478bd9Sstevel@tonic-gate else return (-1); 5057c478bd9Sstevel@tonic-gate } 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate /* 5087c478bd9Sstevel@tonic-gate * "stol" attempts to interpret a collection of characters between delimiters 5097c478bd9Sstevel@tonic-gate * as a decimal digit. It stops interpreting when it reaches a delimiter or 5107c478bd9Sstevel@tonic-gate * when character does not represent a digit. In the first case it returns 5117c478bd9Sstevel@tonic-gate * success and the latter failure. 5127c478bd9Sstevel@tonic-gate */ 5137c478bd9Sstevel@tonic-gate static int 5147c478bd9Sstevel@tonic-gate stol(cp, delimit, ptr, i) 5157c478bd9Sstevel@tonic-gate char *cp; /* ptr to input string */ 5167c478bd9Sstevel@tonic-gate char delimit; /* delimiter */ 5177c478bd9Sstevel@tonic-gate char **ptr; /* left pointing to next del. or */ 5187c478bd9Sstevel@tonic-gate /* illegal character */ 5197c478bd9Sstevel@tonic-gate int *i; /* digit that the string represents */ 5207c478bd9Sstevel@tonic-gate { 5217c478bd9Sstevel@tonic-gate int c = 0; /* current char */ 5227c478bd9Sstevel@tonic-gate int n = 0; /* working copy of i */ 5237c478bd9Sstevel@tonic-gate int neg = 0; /* is number negative */ 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate if (ptr != (char **)0) 5267c478bd9Sstevel@tonic-gate *ptr = cp; /* in case no number is formed */ 5277c478bd9Sstevel@tonic-gate 5287c478bd9Sstevel@tonic-gate if (EMPTY(cp)) 5297c478bd9Sstevel@tonic-gate return (0); 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate if (!isdigit(c = *cp) && (c == '-')) { 5327c478bd9Sstevel@tonic-gate neg++; 5337c478bd9Sstevel@tonic-gate c = *++cp; 5347c478bd9Sstevel@tonic-gate }; 5357c478bd9Sstevel@tonic-gate if (EMPTY(cp) || !isdigit(c)) 5367c478bd9Sstevel@tonic-gate return (0); 5377c478bd9Sstevel@tonic-gate 5387c478bd9Sstevel@tonic-gate while (isdigit(c = *cp) && (*cp++ != '\0')) { 5397c478bd9Sstevel@tonic-gate n *= 10; 5407c478bd9Sstevel@tonic-gate n += c - '0'; 5417c478bd9Sstevel@tonic-gate }; 5427c478bd9Sstevel@tonic-gate if (ptr != (char **)0) 5437c478bd9Sstevel@tonic-gate *ptr = cp; 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate if ((*cp == '\0') || (*cp == delimit)) { 5467c478bd9Sstevel@tonic-gate *i = neg ? -n : n; 5477c478bd9Sstevel@tonic-gate return (1); 5487c478bd9Sstevel@tonic-gate }; 5497c478bd9Sstevel@tonic-gate return (0); 5507c478bd9Sstevel@tonic-gate } 551