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 *
ask_db(dbp,file)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 *
lo_cache(const char * ds)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 *
find_so(const char * ds)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 *
get_lo(dbp,cp,cplen,m,n)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
extract_name(name)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
fix_lo(dbp)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 *
new_dbd(dbdpp,dbp)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
hash(np,nchrs,m)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
rest_ok(str)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
verscmp(const char * c1p,const char * c2p)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
stol(cp,delimit,ptr,i)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