cache_a.out.c revision 7257d1b4d25bfac0c802847390e98a464fd787ac
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* 4.x ld.so directory caching: run-time link-editor specific functions.
*/
#include <dirent.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include "_a.out.h"
#include "cache_a.out.h"
#include "_rtld.h"
#include "msg.h"
static int stol();
static int rest_ok();
static int verscmp();
static void fix_lo();
static int extract_name();
static int hash();
static struct link_object *get_lo();
/*
* Given a db - find the highest shared versioned object. The
* highest versioned object is the .so with a matching major number
* but the highest minor number
*/
char *
const char *file;
{
char *libname, *n;
char *mnp;
char *mjp;
int liblen;
int major = 0;
int to_min;
struct link_object *tlop;
int index;
n = (char *)file;
return (NULL);
return (NULL);
return (NULL);
return (NULL);
/*
* Search appropriate hash bucket for a matching entry.
*/
/* LINTED */
/* LINTED */
libname) == 0)
break;
}
/*
* If no entry was found, we've lost.
*/
return (NULL);
}
/*
* Given a directory name - give back a data base. The data base may have
* orginated from the mmapped file or temporarily created
*/
struct db *
{
}
}
return (dbp);
}
/*
* Build a database for the directory "ds".
*/
static struct db *
{
int fd; /* descriptor on directory */
int n; /* bytes from getdents */
char *cp; /* working char * */
static long bs; /* cached blocksize for getdents */
char *mnp; /* where minor version begins */
char *mjp; /* where major version begins */
int m; /* the major number */
int to_min; /* index into string of minor */
int cplen; /* length of X */
int index; /* the hash value */
/*
* Try to open directory. Failing that, just return silently.
*/
/*
* If we have not yet gotten a buffer for reading directories,
* allocate it now. Size it according to the most efficient size
* for the first directory we open successfully.
*/
if (!buf) {
}
}
/*
* Have a directory, have a buffer. Allocate up a database
* and initialize it.
*/
/*
* Scan the directory looking for shared libraries. getdents()
* failures are silently ignored and terminate the scan.
*/
/* LINTED */
/* LINTED */
/* LINTED */
/* LINTED */
/*
* If file starts with a "lib", then extract the X
* from libX.
*/
continue;
/*
* Is the next component ".so."?
*/
continue;
/*
* Check if next component is the major number and
* whether following components are legal.
*/
continue;
/*
* Have libX.so.major.minor - attempt to add it to the
* cache. If there is another with the same major
* number then the chose the object with the highest
* minor number
*/
/* LINTED */
tlop = (struct link_object *)
continue;
}
/* LINTED */
/* LINTED */
tlop = (struct link_object *)
/*
* Choose the highest minor version
*/
cplen]) == '\0')) {
+ to_min)) > 0)
break;
}
/* LINTED */
/* LINTED */
tlop = (struct link_object *)
break;
}
}
}
return (dbp);
}
/*
* Allocate and fill in the fields for a link_object
*/
static struct link_object *
char *cp; /* ptr. to X of libX */
int cplen; /* length of X */
int m; /* major version */
int n; /* index to minor version */
{
/*
* Allocate a link object prototype in the database heap.
* Store the numeric major (interface) number, but the minor
* number is stored in the database as an index to the string
* representing the minor version. By keeping the minor version
* as a string, "subfields" (i.e., major.minor[.other.fields. etc.])
* are permitted. Although not meaningful to the link editor, this
* permits run-time substitution of arbitrary customer revisions,
* although introducing the confusion of overloading the lo_minor
* field in the database (!)
*/
/* LINTED */
/*
* Allocate space for the complete path name on the host program's
* heap -- as we have to save it from the directory buffer which
* might otherwise get re-used on us. Note that this space
* is wasted -- we can not assume that it can be reclaimed.
*/
/*
* Store the prototype name in the link object in the database.
*/
return (lop);
}
/*
* Pull the "X" from libX, set name to X and return the
* length of X
*/
static int
char **name;
{
char *ls; /* string after LIB root */
char *dp; /* string before first delimiter */
}
}
return (-1);
}
/*
* Make a pass through the data base to set the dbe_name of a dbe. This
* is necessary because there may be several revisions of a library
* but only one will be chosen.
*/
static void
{
int i; /* loop temporary */
/* length of directory pathname */
char *cp; /* working temporary */
char *tp; /* working temporary */
for (i = 0; i < DB_HASH; i++) {
/* LINTED */
/* LINTED */
}
}
}
/*
* Allocate a new dbd, append it after dbdpp and set the dbd_dbp to dbp.
*/
static struct dbd *
{
return (dbdp);
}
/*
* Calculate hash index for link object.
* This is based on X.major from libX.so.major.minor.
*/
static int
char *np; /* X of libX */
int nchrs; /* no of chrs. to hash on */
int m; /* the major version */
{
int h; /* for loop counter */
char *cp; /* working (char *) ptr */
h = (h << 1) + *cp;
h += (h << 1) + m;
h = ((h & 0x7fffffff) % DB_HASH);
return (h);
}
/*
* Test whether the string is of digit[.digit]* format
*/
static int
char *str; /* input string */
{
int dummy; /* integer place holder */
legal = 0;
break;
}
break;
else
/* LINTED */
}
return (legal);
}
/*
* Compare 2 strings and test whether they are of the form digit[.digit]*.
* It will return -1, 0, or 1 depending on whether c1p is less, equal or
* greater than c2p
*/
static int
{
int l_c1p_ok = 0; /* is c1p a legal string */
int c2p_dig = 0; /* int that c1p currently */
/* represents */
int c1p_dig = 0; /* int that c2p currently */
/* represents */
return (0);
return (-1);
return (1);
};
if (!l_c1p_ok)
return (-1);
return (-1);
return (1);
else return (-1);
}
/*
* "stol" attempts to interpret a collection of characters between delimiters
* as a decimal digit. It stops interpreting when it reaches a delimiter or
* when character does not represent a digit. In the first case it returns
* success and the latter failure.
*/
static int
char *cp; /* ptr to input string */
char delimit; /* delimiter */
char **ptr; /* left pointing to next del. or */
/* illegal character */
int *i; /* digit that the string represents */
{
int c = 0; /* current char */
int n = 0; /* working copy of i */
int neg = 0; /* is number negative */
if (ptr != (char **)0)
return (0);
neg++;
c = *++cp;
};
return (0);
n *= 10;
n += c - '0';
};
if (ptr != (char **)0)
*i = neg ? -n : n;
return (1);
};
return (0);
}